Connecting from code
Every MCP SDK can talk to Spaicely; you don't need any software from us. The examples search for a domain on the public server, which needs no account, and then show how to send an access token to https://mcp.spaicely.com/mcp, the signed-in server. Each one was run against our server before it went on this page.
TypeScript
npm install @modelcontextprotocol/sdk
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(new StreamableHTTPClientTransport(new URL("https://mcp.spaicely.com/mcp/public")));
const result = await client.callTool({
name: "domains.search",
arguments: { names: ["bakkerijjansen"], extensions: ["nl", "com"] },
});
for (const found of result.structuredContent.results) console.log(found.domain, found.status);
await client.close();
// signed in: the access token as a header
new StreamableHTTPClientTransport(new URL("https://mcp.spaicely.com/mcp"), {
requestInit: { headers: { Authorization: `Bearer ${token}` } },
});
Node.js 18 or newer, Deno or Bun; the same code runs in a browser.
Python
pip install "mcp>=2"
import asyncio
from mcp import Client
async def main():
async with Client("https://mcp.spaicely.com/mcp/public") as client:
result = await client.call_tool("domains.search", {"names": ["bakkerijjansen"], "extensions": ["nl", "com"]})
for found in result.structured_content["results"]:
print(found["domain"], found["status"])
asyncio.run(main())
# signed in: the access token as a header
from mcp.client.streamable_http import create_mcp_http_client, streamable_http_client
http = create_mcp_http_client(headers={"Authorization": f"Bearer {token}"})
async with Client(streamable_http_client("https://mcp.spaicely.com/mcp", http_client=http)) as client:
...
Python 3.10 or newer.
Go
go get github.com/modelcontextprotocol/go-sdk
package main
import (
"context"
"fmt"
"log"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func main() {
ctx := context.Background()
client := mcp.NewClient(&mcp.Implementation{Name: "my-app", Version: "1.0.0"}, nil)
session, err := client.Connect(ctx, &mcp.StreamableClientTransport{Endpoint: "https://mcp.spaicely.com/mcp/public"}, nil)
if err != nil {
log.Fatal(err)
}
defer session.Close()
result, err := session.CallTool(ctx, &mcp.CallToolParams{
Name: "domains.search",
Arguments: map[string]any{"names": []string{"bakkerijjansen"}, "extensions": []string{"nl", "com"}},
})
if err != nil {
log.Fatal(err)
}
for _, found := range result.StructuredContent.(map[string]any)["results"].([]any) {
domain := found.(map[string]any)
fmt.Println(domain["domain"], domain["status"])
}
}
// signed in: an http.Client that adds the access token
type bearer struct{ token string }
func (b bearer) RoundTrip(req *http.Request) (*http.Response, error) {
req = req.Clone(req.Context())
req.Header.Set("Authorization", "Bearer "+b.token)
return http.DefaultTransport.RoundTrip(req)
}
transport := &mcp.StreamableClientTransport{
Endpoint: "https://mcp.spaicely.com/mcp",
HTTPClient: &http.Client{Transport: bearer{token}},
}
Go 1.25 or newer.
Rust
cargo add rmcp --features client,transport-streamable-http-client-reqwest,reqwest cargo add tokio --features full cargo add serde_json
use rmcp::{
ServiceExt,
model::CallToolRequestParams,
transport::{StreamableHttpClientTransport, streamable_http_client::StreamableHttpClientTransportConfig},
};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.spaicely.com/mcp/public");
let client = ().serve(StreamableHttpClientTransport::from_config(config)).await?;
let arguments = json!({ "names": ["bakkerijjansen"], "extensions": ["nl", "com"] });
let result = client
.call_tool(CallToolRequestParams::new("domains.search").with_arguments(arguments.as_object().unwrap().clone()))
.await?;
for found in result.structured_content.unwrap()["results"].as_array().unwrap() {
println!("{} {}", found["domain"].as_str().unwrap(), found["status"].as_str().unwrap());
}
client.cancel().await?;
Ok(())
}
// signed in: the access token, without "Bearer "
let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.spaicely.com/mcp").auth_header(token);
The reqwest feature brings TLS; without it only http:// works.
Ruby
bundle add mcp faraday base64
require "mcp"
client = MCP::Client.new(transport: MCP::Client::HTTP.new(url: "https://mcp.spaicely.com/mcp/public"))
client.connect(client_info: { name: "my-app", version: "1.0.0" })
response = client.call_tool(name: "domains.search", arguments: { names: ["bakkerijjansen"], extensions: ["nl", "com"] })
response.dig("result", "structuredContent", "results").each do |found|
puts "#{found["domain"]} #{found["status"]}"
end
# signed in: the access token as a header
transport = MCP::Client::HTTP.new(url: "https://mcp.spaicely.com/mcp",
headers: { "Authorization" => "Bearer #{token}" })
The mcp gem needs faraday for its HTTP client, and base64 since Ruby 3.4.
curl
# 1. which tools are there
curl https://mcp.spaicely.com/mcp/public \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
# 2. call one
curl https://mcp.spaicely.com/mcp/public \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": {"name": "domains.search", "arguments": {"names": ["bakkerijjansen"], "extensions": ["nl", "com"]}}}'
# signed in: same requests to /mcp, with the access token curl https://mcp.spaicely.com/mcp -H "Authorization: Bearer $TOKEN" ...
The server is stateless: no session, every POST stands on its own.
An access token comes from the OAuth flow described under Calling MCP without a client library; the TypeScript and Python SDKs can run that flow themselves, the TypeScript one through an authProvider on the transport. There are official SDKs for C#, Java, Kotlin, Swift and PHP too, see modelcontextprotocol.io; they work the same way: a Streamable HTTP transport to the address above, then tools/call.