diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb572ac428a00b4965b5308e51c52a158e66ea16..dce83e0434b352fe10cfbb6bf9c98fec3981a54e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added ###
 
+- Support for server-side scripting via gRPC. The new `ServerSideScriptingService` API still
+  has alpha status and should not be considered stable yet.
+  
 ### Changed ###
 
 ### Deprecated ###
diff --git a/proto/caosdb/CMakeLists.txt b/proto/caosdb/CMakeLists.txt
index f7fa61531e3c135afc139c41337d8a59a3cca39f..1472ed762b7666b8baa3b07dfc868f1823286244 100644
--- a/proto/caosdb/CMakeLists.txt
+++ b/proto/caosdb/CMakeLists.txt
@@ -22,6 +22,7 @@ set(CAOSDB_API_PACKAGES
     caosdb.info.v1
     caosdb.entity.v1
     caosdb.acm.v1alpha1
+    caosdb.scripting.v1alpha1
     )
 
 # pass variable to parent scope
diff --git a/proto/caosdb/scripting/v1alpha1/main.proto b/proto/caosdb/scripting/v1alpha1/main.proto
new file mode 100644
index 0000000000000000000000000000000000000000..c81b485dffb52e6206c380bcdee2c789483ac8ba
--- /dev/null
+++ b/proto/caosdb/scripting/v1alpha1/main.proto
@@ -0,0 +1,119 @@
+//
+// This file is a part of the LinkAhead Project.
+//
+// Copyright (C) 2025 Joscha Schmiedt <joscha@schmiedt.dev>
+// Copyright (C) 2025 IndiScale GmbH <info@indiscale.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+syntax = "proto3";
+
+package caosdb.scripting.v1alpha1;
+
+import "google/protobuf/timestamp.proto";
+
+option java_multiple_files = true;
+option java_package        = "org.caosdb.api.scripting.v1alpha1";
+
+// A named argument for a script
+message NamedArgument {
+  // The name of the argument
+  string name = 1;
+  // The value of the argument
+  string value = 2;
+}
+
+// Request to execute a script on the server side
+message ExecuteServerSideScriptRequest {
+  // The script to execute
+  string script_filename = 1;
+  // The timeout for the script execution in milliseconds
+  int64 timeout_ms = 2;
+  // The positional arguments for the script
+  repeated string positional_arguments = 3;
+  // The named arguments for the script
+  repeated NamedArgument named_arguments = 4;
+  // The files to be used by the script (will be uploaded to the server, not
+  // implemented yet)
+  repeated string script_files = 5;
+  // The authentication token for the script execution. Will be generated by
+  // the server if empty.
+  string auth_token = 6;
+  // Whether the script should be executed asynchronously (not implemented yet)
+  bool run_async = 7;
+}
+
+// The result of a script execution
+enum ServerSideScriptExecutionResult {
+  // The result of the script execution is unspecified
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_UNSPECIFIED = 0;
+  // The script execution was successful
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SUCCESS = 1;
+  // The script execution failed (general/unspecified failure)
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_GENERAL_FAILURE = 2;
+  // The script does not exist
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SCRIPT_DOES_NOT_EXIST = 3;
+  // The script is not executable
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SCRIPT_NOT_EXECUTABLE = 4;
+  // The script execution failed due to a script error
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SCRIPT_ERROR = 5;
+  // The script execution failed during setup, e.g. due to configuration errors
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SCRIPT_SETUP_ERROR = 6;
+  // The script execution timed out
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_SCRIPT_TIMEOUT = 7;
+  // The script execution was cancelled for another reason
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_CANCELLED = 8;
+  // The script execution was denied due to insufficient permissions
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_PERMISSION_DENIED = 9;
+  // The script is running and the result is not yet available (only for
+  // async scripts)
+  SERVER_SIDE_SCRIPT_EXECUTION_RESULT_RUNNING = 10;
+}
+
+// Id of a script execution. This is reserved for later releases to track
+// and manage script executions.
+message ServerSideScriptExecutionId {
+  // Id of the script execution
+  string script_execution_id = 1;
+}
+
+// Response to a script execution request
+message ExecuteServerSideScriptResponse {
+  // Id of the script execution
+  ServerSideScriptExecutionId script_execution_id = 1;
+  // The full command that was executed including all args
+  string call = 2;
+  // The result of the script execution
+  ServerSideScriptExecutionResult result = 3;
+  // Script return code
+  int32 return_code = 4;
+  // The standard output of the script
+  string stdout = 5;
+  // The standard error of the script
+  string stderr = 6;
+  // The start time of the script execution
+  google.protobuf.Timestamp start_time = 7;
+  // The end time of the script execution (empty if the script is still running)
+  google.protobuf.Timestamp end_time = 8;
+  // The duration of the script execution in milliseconds (zero if the script
+  // is still running)
+  int64 duration_ms = 9;
+}
+
+// Service for server-side scripting
+service ServerSideScriptingService {
+  // Executes a script on the server side
+  rpc ExecuteServerSideScript(ExecuteServerSideScriptRequest)
+      returns (ExecuteServerSideScriptResponse) {}
+}