Loading...
Loading...
Compare original and translation side by side
namedescriptioninputSchemaexecutenamedescriptioninputSchemaexecute// Check if the browser supports WebMCP
if ("modelContext" in navigator) {
navigator.modelContext.registerTool({
name: "greet_user",
description: "Returns a personalized greeting for the given name.",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "The person's name" }
},
required: ["name"]
},
execute: ({ name }) => {
document.getElementById("greeting").textContent = `Hello, ${name}!`;
return `Greeted ${name} successfully.`;
}
});
}"modelContext" in navigatorregisterTool// 检查浏览器是否支持WebMCP
if ("modelContext" in navigator) {
navigator.modelContext.registerTool({
name: "greet_user",
description: "Returns a personalized greeting for the given name.",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "The person's name" }
},
required: ["name"]
},
execute: ({ name }) => {
document.getElementById("greeting").textContent = `Hello, ${name}!`;
return `Greeted ${name} successfully.`;
}
});
}"modelContext" in navigatorregisterToolagent.requestUserInteraction()modelContextagent.requestUserInteraction()modelContextadd_itemsearch_flightsset_filtersadd-itemadd_itemtypepropertiesrequiredenumdescriptionadd_itemsearch_flightsset_filtersadd-itemadd_itemtypepropertiesrequiredenumdescriptiondataget_cart_contents"Does stuff with the form""Submits the contact form with the given name, email, and message. Returns a confirmation ID or validation errors."user_emailuser_locationquerymax_resultsdataget_cart_contents"Does stuff with the form""Submits the contact form with the given name, email, and message. Returns a confirmation ID or validation errors."user_emailuser_locationquerymax_resultsset_font_sizeset_font_colorset_font_familydo_everything(instructions)edit_design(instructions)set_font_sizeset_font_colorset_font_familydo_everything(instructions)edit_design(instructions)my-app/
├── index.html
├── style.css
├── script.js # App logic + WebMCP tool registrationmy-app/
├── index.html
├── style.css
├── script.js # App logic
├── webmcp.ts # WebMCP tool definitions and registrationmy-app/
├── index.html
├── style.css
├── script.js # 应用逻辑 + WebMCP工具注册my-app/
├── index.html
├── style.css
├── script.js # 应用逻辑
├── webmcp.ts # WebMCP工具定义与注册window.addEventListener('load', () => {
if ("modelContext" in navigator) {
navigator.modelContext.registerTool({
name: "add_todo",
description: "Add a new todo item to the list. Returns confirmation with the current item count.",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "The text of the todo item" }
},
required: ["text"]
},
annotations: {
readOnlyHint: false,
idempotentHint: false
},
execute: ({ text }) => {
if (!text.trim()) {
return "Error: Todo text cannot be empty.";
}
addTodo(text); // Call your existing app function
renderTodoList(); // Update the UI
return `Added todo: "${text}". You now have ${getTodoCount()} items.`;
}
});
}
});window.addEventListener('load', () => {
if ("modelContext" in navigator) {
navigator.modelContext.registerTool({
name: "add_todo",
description: "Add a new todo item to the list. Returns confirmation with the current item count.",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "The text of the todo item" }
},
required: ["text"]
},
annotations: {
readOnlyHint: false,
idempotentHint: false
},
execute: ({ text }) => {
if (!text.trim()) {
return "Error: Todo text cannot be empty.";
}
addTodo(text); // 调用现有应用函数
renderTodoList(); // 更新UI
return `Added todo: "${text}". You now have ${getTodoCount()} items.`;
}
});
}
});navigator.modelContextwindow.addEventListener('load', ...)navigator.modelContext⚠️ HTTP required:is only available when the page is served over HTTP or HTTPS (e.g.navigator.modelContext). It will not be injected onhttp://localhost:8080URLs. Always run a local dev server during development.file://
window.addEventListener('load', () => {
if ("modelContext" in navigator) {
// WebMCP is supported — register tools here
}
});provideContextnavigator.modelContext.provideContext({
tools: [
{
name: "add-todo",
description: "Add a new todo item to the list",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "The text of the todo item" }
},
required: ["text"]
},
execute: ({ text }, agent) => {
addTodo(text);
return {
content: [
{ type: "text", text: `Added todo: "${text}"` }
]
};
}
}
]
});registerToolunregisterToolnavigator.modelContext.registerTool({
name: "search_flights",
description: "Search for flights with the given parameters.",
inputSchema: {
type: "object",
properties: {
origin: {
type: "string",
description: "3-letter IATA airport code for origin",
pattern: "^[A-Z]{3}$"
},
destination: {
type: "string",
description: "3-letter IATA airport code for destination",
pattern: "^[A-Z]{3}$"
}
},
required: ["origin", "destination"]
},
execute: async ({ origin, destination }) => {
const results = await searchFlights(origin, destination);
return `Found ${results.length} flights from ${origin} to ${destination}.`;
}
});
// Later, when navigating away from search:
navigator.modelContext.unregisterTool("search_flights");navigator.modelContextwindow.addEventListener('load', ...)navigator.modelContext⚠️ 需HTTP环境:仅在页面通过HTTP或HTTPS提供服务时可用(例如navigator.modelContext)。在http://localhost:8080协议的URL下无法注入。开发期间请始终运行本地开发服务器。file://
window.addEventListener('load', () => {
if ("modelContext" in navigator) {
// WebMCP已支持——在此注册工具
}
});provideContextnavigator.modelContext.provideContext({
tools: [
{
name: "add-todo",
description: "Add a new todo item to the list",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "The text of the todo item" }
},
required: ["text"]
},
execute: ({ text }, agent) => {
addTodo(text);
return {
content: [
{ type: "text", text: `Added todo: "${text}"` }
]
};
}
}
]
});registerToolunregisterToolnavigator.modelContext.registerTool({
name: "search_flights",
description: "Search for flights with the given parameters.",
inputSchema: {
type: "object",
properties: {
origin: {
type: "string",
description: "3-letter IATA airport code for origin",
pattern: "^[A-Z]{3}$"
},
destination: {
type: "string",
description: "3-letter IATA airport code for destination",
pattern: "^[A-Z]{3}$"
}
},
required: ["origin", "destination"]
},
execute: async ({ origin, destination }) => {
const results = await searchFlights(origin, destination);
return `Found ${results.length} flights from ${origin} to ${destination}.`;
}
});
// 后续离开搜索页面时:
navigator.modelContext.unregisterTool("search_flights");| Field | Required | Description |
|---|---|---|
| Yes | Unique identifier for the tool |
| Yes | Natural language description of what the tool does |
| Yes | JSON Schema object describing the parameters |
| Yes | Function |
| No | JSON Schema describing the return value structure |
| No | Hints like |
| 字段 | 是否必填 | 描述 |
|---|---|---|
| 是 | 工具的唯一标识符 |
| 是 | 工具功能的自然语言描述 |
| 是 | 描述参数的JSON Schema对象 |
| 是 | 实现工具功能的函数,格式为 |
| 否 | 描述返回值结构的JSON Schema |
| 否 | 提示信息,如 |
executeexecuteparamsinputSchemaagent// Simple text response
execute: ({ query }) => {
return `Found 5 results for "${query}"`;
}
// Structured content response (MCP-aligned)
execute: ({ name }) => {
return {
content: [
{ type: "text", text: `Item "${name}" created successfully.` }
]
};
}
// Return data for the agent to process
execute: () => {
return JSON.stringify(getAppState());
}paramsinputSchemaagent// 简单文本响应
execute: ({ query }) => {
return `Found 5 results for "${query}"`;
}
// 结构化内容响应(与MCP对齐)
execute: ({ name }) => {
return {
content: [
{ type: "text", text: `Item "${name}" created successfully.` }
]
};
}
// 返回供Agent处理的数据
execute: () => {
return JSON.stringify(getAppState());
}success"Light turned on."success: true/falsemessagenew_stateget_*errornew_state// ✅ Success — clear confirmation + updated state
execute: ({ light_id, action }) => {
state.lights[light_id].on = (action === 'on');
renderLight(light_id);
return JSON.stringify({
success: true,
message: `${light_id} light turned ${action}.`,
new_state: { light_id, on: state.lights[light_id].on },
});
}
// ✅ Failure — explicit flag so the agent knows to retry or report
execute: ({ light_id, action }) => {
if (!VALID_IDS.includes(light_id)) {
return JSON.stringify({
success: false,
error: `Unknown light_id "${light_id}". Valid options: ${VALID_IDS.join(', ')}.`,
});
}
// ...
}new_statesuccess"Light turned on."success: true/falsemessagenew_stateget_*errornew_state// ✅ 成功——明确的确认信息 + 更新后的状态
execute: ({ light_id, action }) => {
state.lights[light_id].on = (action === 'on');
renderLight(light_id);
return JSON.stringify({
success: true,
message: `${light_id} light turned ${action}.`,
new_state: { light_id, on: state.lights[light_id].on },
});
}
// ✅ 失败——明确的标志,让Agent知晓需重试或上报错误
execute: ({ light_id, action }) => {
if (!VALID_IDS.includes(light_id)) {
return JSON.stringify({
success: false,
error: `Unknown light_id "${light_id}". Valid options: ${VALID_IDS.join(', ')}.`,
});
}
// ...
}new_stateagent.requestUserInteraction()execute: async ({ product_id }, agent) => {
const confirmed = await agent.requestUserInteraction(async () => {
return new Promise((resolve) => {
const ok = confirm(`Purchase product ${product_id}?`);
resolve(ok);
});
});
if (!confirmed) {
throw new Error("Purchase cancelled by user.");
}
executePurchase(product_id);
return `Product ${product_id} purchased.`;
}agent.requestUserInteraction()execute: async ({ product_id }, agent) => {
const confirmed = await agent.requestUserInteraction(async () => {
return new Promise((resolve) => {
const ok = confirm(`Purchase product ${product_id}?`);
resolve(ok);
});
});
if (!confirmed) {
throw new Error("Purchase cancelled by user.");
}
executePurchase(product_id);
return `Product ${product_id} purchased.`;
}annotations: {
readOnlyHint: true, // Tool only reads data, no side effects
destructiveHint: false, // Tool doesn't delete or irreversibly modify data
idempotentHint: true, // Calling multiple times with same args has same effect
openWorldHint: false // Tool doesn't interact with external systems
}⚠️ Annotation values must be booleans (/true), not strings (false/"true"). Passing strings will cause a runtime validation error ("false",expected: "boolean").code: "invalid_type"
annotations: {
readOnlyHint: true, // 工具仅读取数据,无副作用
destructiveHint: false, // 工具不会删除或不可逆地修改数据
idempotentHint: true, // 使用相同参数多次调用,结果一致
openWorldHint: false // 工具不与外部系统交互
}⚠️ 注释值必须为布尔值(/true),而非字符串(false/"true")。传入字符串会导致运行时验证错误("false",expected: "boolean")。code: "invalid_type"
toolactivatedoutputSchematoolactivatedoutputSchemanavigator.modelContexthttp://https://file://window.addEventListener('load', ...)truefalseinputSchemaexecuteexecutesuccess: true/falsemessagenew_stateerror{ success: false, error: "..." }requestUserInteraction()navigator.modelContexthttp://https://file://window.addEventListener('load', ...)truefalseinputSchemaexecuteexecutesuccess: true/falsemessagenew_stateerror{ success: false, error: "..." }requestUserInteraction()