Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Quickstart

In five minutes you'll have an MCP client connected to ScaiGrid, listing the tool catalog filtered for your permissions, and running a chat completion through it.

You need:

  • A ScaiGrid API key (sgk_...) for a tenant where you have at least models:use and models:list.
  • Python 3.10+ or Node 18+, depending on which sample you run.
  • The MCP SDK for your language: pip install mcp or npm install @modelcontextprotocol/sdk.
bash
1
2
export SCAIGRID_HOST="https://scaigrid.scailabs.ai"
export SCAIGRID_API_KEY="sgk_..."

1. Confirm the transport is up#

The MCP transport is mounted at /mcp on the ScaiGrid host. It does not respond to plain GET — it's a streamable-HTTP transport — but you can verify the host is reachable and your token is accepted by hitting the admin tool-list endpoint:

bash
1
2
curl "$SCAIGRID_HOST/v1/modules/scaimcp/tools" \
  -H "Authorization: Bearer $SCAIGRID_API_KEY"

A 200 with a JSON list of tool names means you're good. A 401 means your token is wrong or expired; a 403 means your role doesn't have scaimcp:access.

2. Connect and list tools#

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import asyncio, os
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def main():
    url = f"{os.environ['SCAIGRID_HOST']}/mcp"
    headers = {"Authorization": f"Bearer {os.environ['SCAIGRID_API_KEY']}"}
    async with streamablehttp_client(url, headers=headers) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()
            for t in tools.tools:
                print(f"{t.name}: {t.description}")

asyncio.run(main())
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from
  "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(
  new URL(`${process.env.SCAIGRID_HOST}/mcp`),
  { requestInit: { headers: {
      Authorization: `Bearer ${process.env.SCAIGRID_API_KEY}` } } }
);
const client = new Client({ name: "qs", version: "0.1" }, { capabilities: {} });
await client.connect(transport);

const { tools } = await client.listTools();
for (const t of tools) console.log(`${t.name}: ${t.description}`);
bash
1
2
3
4
# Inspector via npx — quick interactive UI
npx @modelcontextprotocol/inspector \
  --url "$SCAIGRID_HOST/mcp" \
  --header "Authorization: Bearer $SCAIGRID_API_KEY"

The list you see is filtered for your identity — modules disabled for your tenant are hidden, tools you can't invoke are hidden. A super-admin sees everything; a tenant_user typically sees inference and session tools only.

3. Call a tool#

Run a non-streaming chat completion through inference_chat:

python
1
2
3
4
5
6
7
8
result = await session.call_tool("inference_chat", {
    "model": "scailabs/poolnoodle-omni",
    "messages": [
        {"role": "user", "content": "Say hello in one short sentence."}
    ],
    "max_tokens": 60,
})
print(result.content[0].text)
javascript
1
2
3
4
5
6
7
8
9
const result = await client.callTool({
  name: "inference_chat",
  arguments: {
    model: "scailabs/poolnoodle-omni",
    messages: [{ role: "user", content: "Say hello in one short sentence." }],
    max_tokens: 60,
  },
});
console.log(result.content[0].text);

The response is a single text content block containing a JSON-encoded result with id, model, content, finish_reason, and usage. The usage object is what gets recorded against your tenant budget.

4. List models, then call again#

A typical agent loop: discover what's available, then invoke. models_list returns the frontend model catalog your tenant can use:

python
1
2
models = await session.call_tool("models_list", {})
print(models.content[0].text)

Pick a slug from the response and re-run inference_chat with it.

5. Check the audit trail#

Every MCP call goes through the same accounting and audit pipeline as a REST call. Confirm in two places:

bash
1
2
3
# Token usage for the current period
curl "$SCAIGRID_HOST/v1/accounting/usage?period=day" \
  -H "Authorization: Bearer $SCAIGRID_API_KEY"
bash
1
2
3
# Audit events from your user
curl "$SCAIGRID_HOST/v1/audit/events?actor_user_id=$YOUR_USER_ID&limit=10" \
  -H "Authorization: Bearer $SCAIGRID_API_KEY"

The chat tool call shows up as a normal inference event — there's no separate "MCP" audit category, because MCP is just another front door.

What just happened#

  • Your client opened a streamable-HTTP MCP session against /mcp and authenticated with the bearer token.
  • ScaiMCP resolved the token to a CurrentUser using the same code path as the REST API.
  • list_tools ran the catalog through three filters: core tool permissions, enabled-module gating, and the cloud-MCP aggregator from ScaiLink.
  • call_tool("inference_chat", ...) invoked the same InferenceService.chat that /v1/inference/chat uses — so the dispatcher, accounting, and audit log all behave identically.

Next#

Updated 2026-05-18 15:01:30 View source (.md) rev 12