The kit ships no model service and no default inference endpoint. createPiHarness() requires a configured provider adapter: the resolver option, typed ToolResolver. It receives the page’s tools and current context and returns the next action. The adapter is not a separate mode; every chat turn uses the provider you select.
Choose where inference runs, then pass the resulting object as resolver:
- Browser built-in AI
createResolver() with provider: 'chrome-built-in'. No endpoint or key; needs Chrome’s LanguageModel API.- Your OpenAI-compatible endpoint
createResolver() with baseUrl: '/model-proxy/v1'. The kit posts to baseUrl + '/chat/completions'. Use a same-origin HTTPS proxy for local or self-hosted models; a key held in the browser is visible to the page.- Your server endpoint
createResolver() with server mode (auth.mode: 'server') and an endpoint your app owns. The browser posts the command to that route; the server holds the provider key and returns the selected tool and input. Recommended for production.- Hosted OpenAI
createHostedOpenAIResolver() with accessKey, model, endpoint, and sessionEndpoint. A publishable key is exchanged for a short-lived session; provider secrets stay server-side.- Custom adapter
- Implement
ToolResolver with capabilities.conversation: true, honor single-step requests, purpose: 'summary', cancellation, and request-size limits, and throw on failure.
Server endpoint mode — the browser never sees a provider secret:
import { createResolver } from '@vampaz/webmcp-kit'
// Your server holds the provider key and calls the model.
// The browser only posts the command to this route.
const resolver = await createResolver({
provider: 'openai',
model: 'your-approved-model',
auth: {
mode: 'server',
endpoint: '/api/webmcp/resolve'
}
})
Direct OpenAI-compatible endpoint — for a local model behind your own proxy:
import { createResolver } from '@vampaz/webmcp-kit'
// A same-origin HTTPS proxy in front of LM Studio, Ollama, vLLM, or any
// OpenAI-compatible provider. The kit posts to /model-proxy/v1/chat/completions.
const resolver = await createResolver({
provider: 'openai-compatible',
model: 'your-model-id',
baseUrl: '/model-proxy/v1',
auth: { mode: 'none' }
})
The server endpoint receives { provider, model, message, tools, context, responseSchema, singleStep, purpose } and returns the selected tool and input as JSON. For purpose: 'summary', use the offered reply tool to return a checkpoint, omit action-selection instructions, and reject resolver outcomes and sequences. Keep input schema descriptions in the model prompt. On failure, return a non-2xx status with a { error } body. The installed kit includes the matching docs/resolver-providers.md and docs/pi.md guides for the endpoint contract and controller lifecycle.
Example: use the demo’s hosted OpenAI service
This optional example connects to the standalone demo’s hosted service, which is separate from WebMCP Kit. Use a publishable key for that service and allow your app’s exact origin in its project policy. This Astro example uses a PUBLIC_ variable; Vite apps normally use VITE_.
import { createHostedOpenAIResolver } from '@vampaz/webmcp-kit/hosted'
// Optional example: the standalone demo's hosted service.
const resolver = createHostedOpenAIResolver({
accessKey: import.meta.env.PUBLIC_WEBMCP_PAID_ACCESS_KEY,
model: 'gpt-6-luna',
endpoint: 'https://webmcp.conekto.eu/api/webmcp/resolve',
sessionEndpoint: 'https://webmcp.conekto.eu/api/webmcp/session'
})
The kit exchanges the publishable key for a short-lived session. Provider secrets stay on the server, and the endpoint must support Pi’s single-step requests.
Changing provider means creating a new adapter and a new harness. Destroy the previous controller first.