meritplan.rs WebMCP audit

audited Sep 25, 2026in 16s
68/ 100100% of the applicable check weight evaluated

9 tools registered. Strongest in tool selection, weakest in trust.

Shared experience75
Tool selection100
Tool quality82
Trust0
https://meritplan.rs
Captured view of https://meritplan.rs

Tools

0 read, 0 write, 9 undeclared
Loading map
search_posts: fail

search_posts

Search posts, pages or custom post types on the site.No behaviour hints declared. Agents should treat it as possibly state-changing.
pagehttps://www.meritplan.rs/
implementation
viaimperative
entry pointprovideContext
registered after1387ms
executepresent
api surface
queryrequired
post_typeoptional
per_pageoptional
annotations
read onlynot declared
untrusted contentnot declared
titlenot declared
2 findings
failCanonical entry point
weight 3
Every tool uses the removed provideContext API; register each tool with document.modelContext.registerTool().
fix
// document.modelContext is the canonical entry point - the navigator.modelContext alias is deprecated.
document.modelContext.registerTool({ /* ... */ });
failAnnotations present
weight 5
8 of 8 read-shaped tools do not declare readOnlyHint: true, so an agent has to treat them as possible writes and ask before calling. (Declaring readOnlyHint: false earns nothing - it is the default.)
search_posts, get_post, get_menu, get_site_info, get_categories
fix
{
  name: "search_posts",
  // Declare readOnlyHint: true on tools that truly have no side effects -
  // that is the claim that lets an agent relax confirmation on reads.
  // (false is the default, so declaring it adds no information.)
  annotations: { readOnlyHint: true }
}
tool json
{
  "name": "search_posts",
  "description": "Search posts, pages or custom post types on the site.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Search keywords."
      },
      "post_type": {
        "type": "string",
        "description": "Post type slug (default: any)."
      },
      "per_page": {
        "type": "integer",
        "description": "Results per page (default: 5, max: 20)."
      }
    },
    "required": [
      "query"
    ]
  },
  "annotations": {}
}
Showing search_posts

Findings

Shared experience

75 / 100 · weight 30
not applicableVisible effect
weight 6
Not invoked on this run: this audit did not call any tool. Scheduled re-audits only read the registry; a live audit from the report page calls the tools that declare readOnlyHint: true.
warningPage experience
weight 16
2 of 4 page-experience marks came back short: readability A large number '17' is overlapping the page content, making it hard to read..
readability: weak; obstruction: weak
warningHuman parity
weight 8
The page the person sees came back short of the agent surface (2 of 4 page-experience marks came back short: readability A large number '17' is overlapping the page content, making...), so the two are not sharing an equal experience.
fix
// Make the tool's effect visible on the page the person is looking at:
// update the same UI your existing human flow uses when your_tool_name runs,
// so the person co-browsing sees what the agent just did.
execute: async (args, { signal }) => {
  const result = await performAction(args, signal);
  renderResultInPage(result); // the human-visible half of the same action
  return result;
}

Tool selection

100 / 100 · weight 25
not applicableInvoke success rate
weight 6
Not invoked on this run: this audit did not call any tool. Scheduled re-audits only read the registry; a live audit from the report page calls the tools that declare readOnlyHint: true.
passTool selection
weight 12
An agent chose an existing, callable tool and built a schema-valid call for all 3 canonical intents, each matching the kind of tool its intent needs. Nothing was executed, so this verifies selection, not outcomes.
not applicableCoverage vs. site type
weight 7
This tool set does not place the site in a category with a known expected tool shape, so there is no coverage baseline to score it against.

Tool quality

82 / 100 · weight 25
warningRegistration timing
weight 1
The slowest tool took 1387ms to register, past the 1000ms an agent reading the registry at first paint would wait for.
toolretrieve
retrieve: registered at 1387ms
fix
// Register tools as soon as they're ready, not behind a deferred/async chunk.
document.modelContext.registerTool({ /* ... */ });
failCanonical entry point
weight 3
Every tool uses the removed provideContext API; register each tool with document.modelContext.registerTool().
toolsearch_posts
fix
// document.modelContext is the canonical entry point - the navigator.modelContext alias is deprecated.
document.modelContext.registerTool({ /* ... */ });
warningSchema validity
weight 4
1 of 9 declared input schemas cannot be read by an agent: get_site_info inputSchema.properties is not an object.
toolget_site_info
get_site_info: inputSchema.properties is not an object
fix
{
  name: "get_site_info",
  inputSchema: { type: "object", properties: { /* ... */ }, required: [] }
}
passSchema quality
weight 4
All 8 of 9 tool schemas that declare parameters describe them (the other 1 declares no parameters), and every description stays within Chrome's size guidance.
passNaming quality
weight 2
All 9 tool names are consistent, verb-led, and within Chrome's size guidance.
passStub detection
weight 4
All 9 tools declare an execute handler.
passRegistration errors
weight 2
No tool registration threw during the capture.
passDescription quality
weight 5
2 of 9 tool descriptions leave an agent guessing: get_post Omits what comes back, and how it differs from get_markdown_content..
toolget_post
get_post: weak; get_menu: weak

Trust

0 / 100 · weight 20
failAnnotations present
weight 5
8 of 8 read-shaped tools do not declare readOnlyHint: true, so an agent has to treat them as possible writes and ask before calling. (Declaring readOnlyHint: false earns nothing - it is the default.)
toolsearch_posts
search_posts, get_post, get_menu, get_site_info, get_categories
fix
{
  name: "search_posts",
  // Declare readOnlyHint: true on tools that truly have no side effects -
  // that is the claim that lets an agent relax confirmation on reads.
  // (false is the default, so declaring it adds no information.)
  annotations: { readOnlyHint: true }
}
not applicableAnnotation mismatch
weight 5
No tool declares a readOnlyHint, so there is no safety claim to contradict.
not applicableUntrusted content hint
weight 3
No tool's contract suggests it returns text written by somebody other than the site, so there is nothing to flag as untrusted.
not applicableHint vs. observed
weight 4
Not invoked on this run: this audit did not call any tool. Scheduled re-audits only read the registry; a live audit from the report page calls the tools that declare readOnlyHint: true.
warningInjection surface
weight 3
3 of 9 tools carry instruction-shaped text in their own metadata: get_markdown_content description instructs agent on ideal consumption.
toolget_markdown_content
get_markdown_content: description instructs agent on ideal consumption; get_llms_txt: description instructs agent to understand site at a glance; retrieve: description instructs agent to use this before another tool
fix
{
  name: "get_markdown_content",
  // Metadata DESCRIBES the tool - it never addresses the agent reading it.
  // Rewrite any name, description, title, or schema field description that
  // instructs the agent (which tool to prefer, what to output, rules to
  // ignore) so it states what the tool does and what it returns instead.
  description: "Searches the catalog and returns matching items with prices."
}

Tool selection

100% across 3 intents
I want to search posts on this site.ok
chosesearch_postsexpected search postskind matched
arguments
{
  "query": "posts"
}
I want to get post on this site.ok
choseget_postexpected get postkind matched
arguments
{
  "id": 1
}
I want to submit contact form on this site.ok
chosesubmit_contact_formexpected submit contact formkind matched
arguments
{
  "form_id": 1,
  "fields": {}
}
model: gemini-2.5-flash

Add the tools this site is missing

Our scanner reads your website and suggests the right WebMCP tools for it.
Reads the site's public pages; takes a few seconds.
The open source webmcp plugin teaches your coding agent to audit a site, implement tools on document.modelContext, and verify them in a real browser. npx @ora-ai/webmcp-verify runs the verification on its own. No signup, no hosted service.
how this was captured
observed via
capture shim (Chromium 151.0.7922.34)
chrome
151.0.7922.34
capture shim
v3
spec snapshot
2026-08-26
mode
fast
pages
1 - entry page only
tools
9
invoked
not invoked; a live audit calls them
run time
16s
finished
Sep 25, 2026
Checked the way in-browser agents discover tools: the top-level document's modelContext registry, read after the page settles.