06 SDKs & host

A provider in three methods

Every SDK is zero-dependency, speaks the line-oriented JSON wire over stdio, and is validated by the same Rust conformance oracle. Implement info(), capabilities(), and query(); the runtime loop handles the rest.

The stdio runtime — runStdioProvider / run_stdio_provider / RunStdioProvider — drives the whole lifecycle a host expects: handshake, query (echoing the correlation id), verify, shutdown, and it stays alive with a typed error on a malformed line rather than crashing. Each SDK also exports the canonical budget rule.

TypeScript

Published on npm as @contextgraphprotocol/typescript-sdk.

npm install @contextgraphprotocol/typescript-sdktypescript
import {
  runStdioProvider,
  budgetTokens,
  type Provider,
} from "@contextgraphprotocol/typescript-sdk";

const provider: Provider = {
  info: () => ({
    name: "my-docs-provider",
    version: "0.1.0",
    data_flow: { reads: true, writes: false, egress: false,
                 egress_scopes: ["local-only"] },
  }),
  capabilities: () => ({
    query: { kinds: ["doc"] }, correlation: true, verify: true,
  }),
  query: () => {
    const content = "Install the binding, then implement the required methods.";
    return {
      frames: [{
        id: "doc:1", kind: "doc", title: "Getting started",
        content,
        content_digest: `sha256:${"11".repeat(32)}`,
        score: 0.9,
        token_cost: budgetTokens(content),
        citation_label: "start.md L1-10",
      }],
      truncated: false,
    };
  },
};

runStdioProvider(provider);

Python

The contextgraph_sdk package lives in the repository under sdk/python — stdlib-only, typed (py.typed). Any object with the three methods is a provider.

sdk/python — contextgraph_sdkpython
from contextgraph_sdk import run_stdio_provider, budget_tokens

class MyDocsProvider:
    def info(self):
        return {"name": "my-docs-provider", "version": "0.1.0",
                "data_flow": {"reads": True, "writes": False,
                              "egress": False,
                              "egress_scopes": ["local-only"]}}

    def capabilities(self):
        return {"query": {"kinds": ["doc"]},
                "correlation": True, "verify": True}

    def query(self, query):
        content = "Install the binding, then implement the required methods."
        return {"frames": [{
            "id": "doc:1", "kind": "doc", "title": "Getting started",
            "content": content,
            "content_digest": "sha256:" + ("11" * 32),
            "score": 0.9,
            "token_cost": budget_tokens(content),
            "citation_label": "start.md L1-10"}],
            "truncated": False}

run_stdio_provider(MyDocsProvider())

Go

Module github.com/macanderson/context-graph-protocol/sdk/go/contextgraph. Implement cg.Verifier to answer verification.

sdk/go — package contextgraphgo
package main

import cg "github.com/macanderson/context-graph-protocol/sdk/go/contextgraph"

type myProvider struct{}

func (myProvider) Info() cg.ProviderInfo {
	return cg.ProviderInfo{Name: "my-docs-provider", Version: "0.1.0",
		DataFlow: cg.DataFlow{Reads: true,
			EgressScopes: []string{"local-only"}}}
}

func (myProvider) Capabilities() cg.Capabilities {
	return cg.Capabilities{Query: cg.QueryCapability{Kinds: []string{"doc"}},
		Correlation: true}
}

func (myProvider) Query(_ cg.ContextQuery) cg.ContextQueryResult {
	content := "Install the binding, then implement the required methods."
	return cg.ContextQueryResult{Frames: []cg.ContextFrame{{
		ID: "doc:1", Kind: "doc", Title: "Getting started",
		Content: content, Score: 0.9,
		TokenCost:     cg.BudgetTokens(content),
		CitationLabel: "start.md L1-10"}}}
}

func main() { cg.RunStdioProvider(myProvider{}) }

Validate any of them

The shared oracleshell
./.github/scripts/conformance-external.sh -- node dist/examples/example-docs.js
./.github/scripts/conformance-external.sh -- python3 examples/example_docs.py
./.github/scripts/conformance-external.sh -- ./cg-go-example

The host side

contextgraph-host is the Rust host runtime: provider discovery, stdio and streamable-HTTP transports, capability negotiation, budget-honest fan-out routing, and egress consent gating. Register providers in-process, as child processes, or as remote HTTP endpoints; query_all fans out concurrently with per-provider isolation — a crashed child never affects the others — and classifies budget liars so their frames are dropped and reported.

Composition is deterministic: frames are emitted in canonical FrameId order, independent of arrival order, inside explicit <frame> fences as quoted material. Stable prefixes turn provider prompt caches from an accident into a contract — the worked example in the context-reuse note shows a ~7× reduction on the context portion of a 20-turn session.