TypeGPU Runtime Inspector MCP
Local stdio MCP server for validating TypeGPU code in Chromium with WebGPU.
It loads TypeGPU inspection modules through Vite, creates a browser GPUDevice,
and reports generated WGSL, shader compilation messages, WebGPU validation
errors, bind group layout stats, console/page errors, and recorded GPU calls.
Quick Setup
Use npx from the client you want to configure:
npx typegpu-runtime-inspector-mcp@latest setup codex
npx typegpu-runtime-inspector-mcp@latest setup claude
npx typegpu-runtime-inspector-mcp@latest setup opencodeConfigure every supported client found on PATH:
npx typegpu-runtime-inspector-mcp@latest setup allThe setup command registers a local MCP server named typegpu_inspector and
pins it to the package version that performed setup, for example:
npx typegpu-runtime-inspector-mcp@0.2.1Existing typegpu_inspector entries are left unchanged unless --upgrade or
--force is provided.
Upgrade From v0.1
If you installed the first release with setup, your MCP client is pinned to
that exact package version. Re-run setup with --upgrade to update an existing
typegpu_inspector entry that already points at this npm package:
npx typegpu-runtime-inspector-mcp@latest setup codex --upgrade
npx typegpu-runtime-inspector-mcp@latest setup claude --upgrade
npx typegpu-runtime-inspector-mcp@latest setup opencode --upgradeOr update every supported client found on PATH:
npx typegpu-runtime-inspector-mcp@latest setup all --upgradeThen restart the MCP client so it launches the new server process. You can check the local environment with:
npx typegpu-runtime-inspector-mcp@latest doctor--upgrade only replaces entries that already reference this npm package. If a
client has a custom typegpu_inspector command, use --force to replace it
intentionally.
Run a local environment check:
npx typegpu-runtime-inspector-mcp@latest doctorRequirements:
- Node.js 20 or newer
- Local filesystem access to the inspected project
- Playwright Chromium with WebGPU support
playwright-chromium is a runtime dependency of this package. If lifecycle
scripts were skipped during install, enable them and reinstall, then run
doctor again.
Manual Client Config
Codex (~/.codex/config.toml):
[mcp_servers.typegpu_inspector]
command = "npx"
args = ["typegpu-runtime-inspector-mcp@<version>"]Codex CLI:
codex mcp add typegpu_inspector -- npx typegpu-runtime-inspector-mcp@<version>Claude Code:
claude mcp add --transport stdio --scope user typegpu_inspector -- npx typegpu-runtime-inspector-mcp@<version>OpenCode:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"typegpu_inspector": {
"type": "local",
"command": ["npx", "typegpu-runtime-inspector-mcp@<version>"],
"enabled": true
}
}
}MCP Tools
Default discovery exposes three agent-facing tools:
inspect_typegpu: run a browser/WebGPU inspection from a probe, inspection module, or exported symbols.list_typegpu_exports: scan one module and suggest symbol targets forinspect_typegpu.resolve_typegpu_context: explain inferred roots, dependency sources, warnings, and next actions without launching a browser.
inspect_typegpu
Preferred tool for agents. Accepted target variants:
probe: function body for quick inline probes.module: path to an inspection module that exportsinspect.symbols: exported symbols from an existing module, usually afterlist_typegpu_exports.
The MCP infers project/package/workspace roots, local TypeGPU dependencies, and
Vite config. Add project.root, project.dependencyAliases,
target.virtualPath, or environment fields only when warnings or diagnostics
ask for them.
In TypeGPU monorepos, package resolution can still fall back to the MCP package
when the current package does not expose a node_modules/typegpu workspace
link. Check dependencySummary.hasBundledTypegpuFallback and warnings. Retry
with project.root anchored to the workspace root and a package-root alias
through project.dependencyAliases instead of aliasing individual subpaths:
{
"project": {
"root": ".",
"dependencyAliases": {
"typegpu": "packages/typegpu/src"
}
}
}That one alias covers typegpu, typegpu/data, typegpu/std, and
typegpu/common. For inline probes that import project files, set
target.virtualPath inside the inspected package so relative imports resolve
from the same location as the source being tested.
Quick probe:
{
"target": {
"kind": "probe",
"body": "const main = tgpu.computeFn({ workgroupSize: [1] })(() => { 'use gpu'; }); return { label: 'main', kind: 'compute-pipeline', value: main };"
}
}Existing exported symbols:
{
"target": {
"kind": "symbols",
"modulePath": "src/shaders.ts",
"targets": [{ "kind": "compute-pipeline", "compute": "mainCompute" }]
}
}Inspection modules export inspect by default:
export async function inspect({ root, device, tgpu, d, std, common }) {
const main = tgpu.computeFn({ workgroupSize: [1] })(() => {
'use gpu';
});
return {
label: 'main',
kind: 'compute-pipeline',
value: main,
};
}Use target.kind: "module" for these files:
{
"target": {
"kind": "module",
"path": "src/inspect-particle-step.ts"
}
}The context contains:
root: TypeGPU root backed by the inspector browser device.device: recordedGPUDeviceproxy.tgpu,d,std,common: TypeGPU imports resolved for the inspected project.
Return a target or an array of targets:
{
label?: string;
kind?: 'compute-pipeline' | 'render-pipeline' | 'resolvable';
value?: unknown;
create?: () => unknown;
unwrap?: boolean;
}Plain returned values are treated as { value }. Compute pipeline targets may
return a TypeGPU compute entrypoint; the inspector creates the pipeline. Use
create when construction should happen during target attribution, especially
for render pipelines and descriptor-heavy probes.
return {
label: 'render',
kind: 'render-pipeline',
create: () =>
root.createRenderPipeline({
vertex: common.fullScreenTriangle,
fragment,
targets: { format: 'bgra8unorm' },
}),
};If kind is omitted on a create target, the inspector infers it from the
created TypeGPU pipeline when possible.
list_typegpu_exports
Statically scans a module and returns:
exports: all exported symbols found.likelyTypegpuExports: exports that look like TypeGPU symbols.suggestedSymbolTargets: ready-to-copyinspect_typegpu.target.targetsentries when possible.
{
"modulePath": "src/shaders.ts"
}resolve_typegpu_context
Returns sanitized resolvedContext, dependencySummary, warnings, and
nextActions for a target path. Agent-facing outputs replace local absolute
paths with labels such as <projectRoot>, <packageRoot>, <workspaceRoot>,
and <mcpPackage>.
{
"targetPath": "apps/demo/src/shaders.ts"
}Agent Examples
Quick probe:
{
"target": {
"kind": "probe",
"body": "const fragment = tgpu.fragmentFn({ in: { uv: d.vec2f }, out: d.vec4f })(({ uv }) => { 'use gpu'; return d.vec4f(uv, 0, 1); }); return { label: 'render', kind: 'render-pipeline', create: () => root.createRenderPipeline({ vertex: common.fullScreenTriangle, fragment, targets: { format: 'bgra8unorm' } }) };"
}
}Inspection file:
{
"project": { "root": "/path/to/project" },
"target": {
"kind": "module",
"path": "src/inspect-particle-step.ts"
}
}Probe with relative imports:
{
"project": { "root": "/path/to/project" },
"target": {
"kind": "probe",
"virtualPath": "src/typegpu-mcp-probe.ts",
"body": "const { helper } = await import('./helper'); return { label: 'helper', kind: 'resolvable', value: helper };"
}
}Browser Setup And Assets
Use these fields when the inspected module expects DOM nodes, globals, static assets, or non-standard import paths:
{
"target": {
"kind": "module",
"path": "src/examples/image-processing/blur/index.ts"
},
"environment": {
"documentHtml": "<canvas width=\"512\" height=\"512\"></canvas>",
"browserSetup": "window.__TEST_MODE__ = true;",
"staticAssetRoutes": [
{ "urlPrefix": "/TypeGPU", "directory": "public" },
{ "urlPrefix": "/", "directory": "public" }
]
}
}Fields:
documentHtml: assigned todocument.body.innerHTMLbefore import.browserSetup: browser JavaScript executed before import withroot,device,tgpu,d,std, andcommonparameters.staticAssetRoutes: serves files from local directories through the inspector Vite server.features: WebGPU features to request from the adapter.strictNames: deterministic TypeGPU generated names. Defaults totrue.viteConfigPath: optional project Vite config. Low-level calls resolve it relative tocwd; agent-facing project hints resolve relative paths from the target package first, then project/workspace roots.
Output
inspect_typegpu mirrors the most useful result fields at the top level:
summary: compact target, pipeline, console, and compilation counts.targets: per-target status, diagnostics, pipeline creation, and optional WGSL.dependencySummary: core TypeGPU source routing and bundled fallback flags.warnings: sanitized context/dependency warnings.nextActions: concrete retry hints.inspection: the formatted report kept for compatibility.
Agent-facing outputs sanitize local absolute paths into labels such as
<projectRoot>, <packageRoot>, <workspaceRoot>, and <mcpPackage>.
Default output is compact. Controls:
verbosity:"summary"(default),"normal", or"full".includeWgsl: include WGSL in targets and shader-module descriptors. Defaults totrueonly for"full".includeCalls: include recorded GPU calls. Defaults totrueonly for"full".maxWgslBytes: truncate each included WGSL string to this many UTF-8 bytes.diagnosticsOnly: return diagnostics, target status, console messages, and page errors.
inspectBody, inlineCode, setupBody, and browserSetup are JavaScript or
TypeScript source snippets. Pass actual newline characters in these fields when
you need multiple lines; double-escaped text such as \\nconst x = 1 is parsed
as literal source and will fail.
{
"target": {
"kind": "probe",
"body": "return { label: 'main', kind: 'resolvable', value: helper };"
},
"output": {
"verbosity": "normal",
"includeWgsl": true,
"maxWgslBytes": 4000
}
}Common diagnostic codes:
plain-object-not-inspectablewrapper-requiredslot-binding-requiredpipeline-resource-shapepipeline-validated-without-recorded-creationraw-webgpu-pipeline-unsupportedtypegpu-fragment-function-not-resolvablemodule-import-failedcanvas-dom-setup-requireddirect-symbol-inspectiontypegpu-random-resolution-failed
Local Development
pnpm install
pnpm startChecks:
pnpm typecheck
pnpm test
pnpm test:browserBrowser tests require Playwright Chromium with WebGPU support. If Chromium is missing, run:
pnpm exec playwright install chromium