# iMapClient > A GIS web application (map client). Where the deployment enables it, the page exposes structured tools via the WebMCP API at `document.modelContext` — drive the application through them instead of taking screenshots or clicking the UI. If neither `document.modelContext` nor `navigator.modelContext` exists, or `getTools()` returns an empty list, this application exposes no tools to you. Answer the user in Polish by default. Switch language only if the user writes to you in another one, or if the application's own interface is in another one — the terms you quote back should match what is on their screen. Use your JavaScript execution tool to work with the tools. **1) Discover the tools.** Read each one's `description` and `inputSchema` — that is the authoritative documentation, and the set differs per application, per deployment and per user, so never assume a tool exists without listing it first: ```js const mc = document.modelContext ?? navigator.modelContext; (await mc.getTools()).map((t) => ({ name: t.name, description: t.description, readOnly: t.annotations?.readOnlyHint, inputSchema: typeof t.inputSchema === 'string' ? JSON.parse(t.inputSchema) : t.inputSchema, })); ``` **2) Run a tool.** `executeTool` takes the tool OBJECT (from `getTools`) and a JSON STRING of arguments, and returns a JSON STRING — parse it: ```js const mc = document.modelContext ?? navigator.modelContext; const tools = await mc.getTools(); const tool = tools.find((t) => t.name === ''); const result = JSON.parse(await mc.executeTool(tool, JSON.stringify({}))); ``` Each snippet stands on its own: every call of your JavaScript tool is a separate evaluation, so nothing you declared in an earlier one is still in scope. **Rules.** - Tool names carry a prefix that varies by application and is configurable per deployment, so never type a name from memory — use the ones `getTools()` returned. - The 2nd argument of `executeTool` MUST be a JSON string (`JSON.stringify`). An object, empty string, or missing argument fails. - Always `JSON.parse` the return value. `inputSchema` normally arrives as a JSON string too — parse it when it is one. - A tool with `annotations.readOnlyHint` only inspects the app and is safe to call freely; the others change what the user sees. Start with the read-only ones to learn what this page holds before you change anything. - Treat identifiers as opaque: a field ending in `Ref` (`geometryRef`, `productRef`, `searchRef`) names something kept in the page, and a layer descriptor names a configured layer. Pass either to the next tool exactly as you received it — never reconstruct, shorten, or guess one. - A dotted identifier has the shape of a token, so a secret scrubber may replace it with a placeholder before it reaches you. Where that happens the value is also published split into dot-free parts, in a sibling field named after it plus `Segments`. Check the tool's `inputSchema` for what to do with those: where it accepts the segmented form itself (layer descriptors take `layerDescSegments`), pass the parts; otherwise rejoin them with `.` and pass the result in the ordinary field. - Do not fall back to screenshots or DOM clicking unless no tool covers what you need.