Importing MCP servers
Before you can reference an MCP server in a profile or a run, it must be imported into your Scope deployment. Importing registers the server's connection details — transport type, URL or command, and any secrets — so that workers can start the server automatically when a run begins.
Transport types
Section titled “Transport types”Scope supports three MCP transport types:
| Type | When to use | Key fields |
| --- | --- | --- |
| http | The MCP server is a remote HTTP endpoint. | url, headers |
| sse | The MCP server uses Server-Sent Events. | url, headers |
| stdio | The MCP server runs as a local process. | command, args, env |
Server IDs (slugs)
Section titled “Server IDs (slugs)”Every MCP server has an _id that acts as its slug throughout
the system. The ID must be lowercase alphanumeric plus
hyphens, matching the pattern:
^[a-z0-9]([a-z0-9-]*[a-z0-9])?$Examples: filesystem, github, my-custom-tools.
Importing from the Portal
Section titled “Importing from the Portal”- Open MCP Servers in the Portal sidebar.
- Click Add MCP Server.
- Fill in the slug (
_id), display name, transport type, and connection details (URL or command). - Submit. The server is registered and immediately available for use in profiles.
Importing via the REST API
Section titled “Importing via the REST API”Use POST /api/v1/mcp/servers to register an MCP server:
curl --request POST \ --url https://your-scope.example.com/api/v1/mcp/servers \ --header 'Content-Type: application/json' \ --data '{ "_id": "github", "name": "GitHub MCP Server", "type": "http", "url": "https://mcp.example.com/github", "description": "Provides GitHub tools to the agent"}'const url = 'https://your-scope.example.com/api/v1/mcp/servers';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"_id":"github","name":"GitHub MCP Server","type":"http","url":"https://mcp.example.com/github","description":"Provides GitHub tools to the agent"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers"
payload = { "_id": "github", "name": "GitHub MCP Server", "type": "http", "url": "https://mcp.example.com/github", "description": "Provides GitHub tools to the agent"}headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers"
payload := strings.NewReader("{\n \"_id\": \"github\",\n \"name\": \"GitHub MCP Server\",\n \"type\": \"http\",\n \"url\": \"https://mcp.example.com/github\",\n \"description\": \"Provides GitHub tools to the agent\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"_id\": \"github\",\n \"name\": \"GitHub MCP Server\",\n \"type\": \"http\",\n \"url\": \"https://mcp.example.com/github\",\n \"description\": \"Provides GitHub tools to the agent\"\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers"), Content = new StringContent("{\n \"_id\": \"github\",\n \"name\": \"GitHub MCP Server\",\n \"type\": \"http\",\n \"url\": \"https://mcp.example.com/github\",\n \"description\": \"Provides GitHub tools to the agent\"\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Request fields
Section titled “Request fields”| Field | Type | Required | Description |
| --- | --- | --- | --- |
| _id | string | ✅ | Server slug (lowercase alphanumeric + hyphens). |
| name | string | ✅ | Human-readable display name. |
| type | string | ✅ | "http", "sse", or "stdio". |
| url | string | — | Server URL (for http and sse). |
| command | string | — | Executable to run (for stdio). |
| args | string[] | — | Arguments passed to the command (for stdio). |
| env | object | — | Environment variables for the process (for stdio). |
| headers | array | — | Custom HTTP headers (for http / sse). Each entry has name and value. |
| sessionMode | string | — | "stateful" or "stateless". |
| version | string | — | Server version string. |
| description | string | — | Free-form description. |
The endpoint uses upsert semantics — it returns 201 for a new server or 200 if the server already exists and was updated. A previously soft-deleted server is restored.
stdio example
Section titled “stdio example”curl --request POST \ --url https://your-scope.example.com/api/v1/mcp/servers \ --header 'Content-Type: application/json' \ --data '{ "_id": "local-tools", "name": "Local Tools", "type": "stdio", "command": "npx", "args": ["-y", "@example/mcp-tools"], "env": { "API_KEY": "sk-..." }}'const url = 'https://your-scope.example.com/api/v1/mcp/servers';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"_id":"local-tools","name":"Local Tools","type":"stdio","command":"npx","args":["-y","@example/mcp-tools"],"env":{"API_KEY":"sk-..."}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers"
payload = { "_id": "local-tools", "name": "Local Tools", "type": "stdio", "command": "npx", "args": ["-y", "@example/mcp-tools"], "env": { "API_KEY": "sk-..." }}headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers"
payload := strings.NewReader("{\n \"_id\": \"local-tools\",\n \"name\": \"Local Tools\",\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@example/mcp-tools\"],\n \"env\": { \"API_KEY\": \"sk-...\" }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"_id\": \"local-tools\",\n \"name\": \"Local Tools\",\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@example/mcp-tools\"],\n \"env\": { \"API_KEY\": \"sk-...\" }\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers"), Content = new StringContent("{\n \"_id\": \"local-tools\",\n \"name\": \"Local Tools\",\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@example/mcp-tools\"],\n \"env\": { \"API_KEY\": \"sk-...\" }\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Headers example (http / sse)
Section titled “Headers example (http / sse)”curl --request POST \ --url https://your-scope.example.com/api/v1/mcp/servers \ --header 'Content-Type: application/json' \ --data '{ "_id": "secure-endpoint", "name": "Secure Endpoint", "type": "sse", "url": "https://mcp.example.com/sse", "headers": [ { "name": "Authorization", "value": "Bearer tok_..." } ]}'const url = 'https://your-scope.example.com/api/v1/mcp/servers';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"_id":"secure-endpoint","name":"Secure Endpoint","type":"sse","url":"https://mcp.example.com/sse","headers":[{"name":"Authorization","value":"Bearer tok_..."}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers"
payload = { "_id": "secure-endpoint", "name": "Secure Endpoint", "type": "sse", "url": "https://mcp.example.com/sse", "headers": [ { "name": "Authorization", "value": "Bearer tok_..." } ]}headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers"
payload := strings.NewReader("{\n \"_id\": \"secure-endpoint\",\n \"name\": \"Secure Endpoint\",\n \"type\": \"sse\",\n \"url\": \"https://mcp.example.com/sse\",\n \"headers\": [\n { \"name\": \"Authorization\", \"value\": \"Bearer tok_...\" }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"_id\": \"secure-endpoint\",\n \"name\": \"Secure Endpoint\",\n \"type\": \"sse\",\n \"url\": \"https://mcp.example.com/sse\",\n \"headers\": [\n { \"name\": \"Authorization\", \"value\": \"Bearer tok_...\" }\n ]\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers"), Content = new StringContent("{\n \"_id\": \"secure-endpoint\",\n \"name\": \"Secure Endpoint\",\n \"type\": \"sse\",\n \"url\": \"https://mcp.example.com/sse\",\n \"headers\": [\n { \"name\": \"Authorization\", \"value\": \"Bearer tok_...\" }\n ]\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Secret handling
Section titled “Secret handling”Environment variables (env) and custom headers (headers) may
contain secrets such as API keys. Scope masks secret values in API
responses.
- On read, secret values are masked as
"<secret>"— you will never see the plaintext in GET responses. - On update, sending
"<secret>"or""for a value tells Scope to keep the existing secret unchanged. Sending a real value overwrites it. Omitting a key deletes it.
You cannot provide both env and headers on the same server.
Use env for stdio servers and headers for http / sse
servers.
Listing MCP servers
Section titled “Listing MCP servers”curl --request GET \ --url https://your-scope.example.com/api/v1/mcp/serversconst url = 'https://your-scope.example.com/api/v1/mcp/servers';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers"
response = requests.get(url)
print(response.json())package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers") .get() .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Get, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers"),};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Returns all active (non-deleted) servers sorted alphabetically
by _id. Secret values are never included in list responses.
Getting a single server
Section titled “Getting a single server”curl --request GET \ --url https://your-scope.example.com/api/v1/mcp/servers/githubconst url = 'https://your-scope.example.com/api/v1/mcp/servers/github';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers/github"
response = requests.get(url)
print(response.json())package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers/github"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers/github") .get() .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Get, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers/github"),};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Returns the server details. Secret fields are present but
masked as "<secret>".
Updating a server
Section titled “Updating a server”Use PUT /api/v1/mcp/servers/:id to update any field. All
fields are optional — only the fields you include are changed:
curl --request PUT \ --url https://your-scope.example.com/api/v1/mcp/servers/github \ --header 'Content-Type: application/json' \ --data '{ "description": "Updated description", "url": "https://mcp-v2.example.com/github"}'const url = 'https://your-scope.example.com/api/v1/mcp/servers/github';const options = { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: '{"description":"Updated description","url":"https://mcp-v2.example.com/github"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers/github"
payload = { "description": "Updated description", "url": "https://mcp-v2.example.com/github"}headers = {"Content-Type": "application/json"}
response = requests.put(url, json=payload, headers=headers)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers/github"
payload := strings.NewReader("{\n \"description\": \"Updated description\",\n \"url\": \"https://mcp-v2.example.com/github\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"description\": \"Updated description\",\n \"url\": \"https://mcp-v2.example.com/github\"\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers/github") .put(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Put, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers/github"), Content = new StringContent("{\n \"description\": \"Updated description\",\n \"url\": \"https://mcp-v2.example.com/github\"\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}If you change the transport type (e.g. from stdio to http),
any stored secrets are automatically deleted to prevent
misinterpretation.
Deleting a server
Section titled “Deleting a server”Deleting is a soft delete — the server disappears from lists and can no longer be added to new profiles, but past runs that used it are unaffected.
curl --request DELETE \ --url https://your-scope.example.com/api/v1/mcp/servers/githubconst url = 'https://your-scope.example.com/api/v1/mcp/servers/github';const options = {method: 'DELETE'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/mcp/servers/github"
response = requests.delete(url)
print(response.json())package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/mcp/servers/github"
req, _ := http.NewRequest("DELETE", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/mcp/servers/github") .delete(null) .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Delete, RequestUri = new Uri("https://your-scope.example.com/api/v1/mcp/servers/github"),};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Returns 204 on success.
Using imported servers in profiles
Section titled “Using imported servers in profiles”After importing, reference servers in a profile's mcpServers
array by their slug:
{ "mcpServers": ["filesystem", "github"]}The agent gains access to whatever tools the MCP server exposes. For more on how MCP servers fit into profiles, see Using MCP servers, skills & extensions.
- Register before you profile. MCP servers must be imported before they can appear in a profile. Import first, then create the profile.
- Use
stdiofor local tools. If the MCP server is a CLI tool or npm package,stdiokeeps everything self-contained. - Use
httporssefor shared services. Remote MCP servers used by multiple profiles benefit from a single centralized deployment. - Rotate secrets via update. Send the new value in a PUT request to replace the existing secret.