MarkMesh — trademark portfolio over MCP
This skill drives the MarkMesh MCP server. MarkMesh is a multi-tenant
trademark-management platform; this server exposes a customer's portfolio
(trademarks, filings, deadlines, clients) plus live trademark-office
search/import as MCP tools, scoped to the API key's organisation.
If the MarkMesh MCP tools are not available in this session, the server
isn't configured — point the user to SETUP.md (get an API key from the
MarkMesh app, add the connector to Claude Desktop, restart). Don't invent a
local fallback; there is no local data.
How auth & scoping work (read this first)
- Every tool runs as the API key's organisation. You only ever see that
org's data — never assume you can reach another firm's or client's records.
- Two key types:
mm_live_* → real production portfolio;
mm_test_* → sandbox. Tell the user which one is active if it
matters. The sandbox isolates the portfolio (trademarks, filings,
clients, watches), NOT office search: search_office and
search_conflicts read the same public register corpus either way, so
a sandbox search returns real marks. Do not tell a user their sandbox
search results are fake.
- Calls count against the key's rate limit (live ~300/min, test ~60/min) —
the same budget as the REST API. Don't poll in tight loops; batch your
reasoning and make deliberate calls.
- Authorisation is enforced server-side by org policies. A tool returning an
empty list usually means "nothing in your org matches", not an error.
Tools
Reads (each supports filter, sort, limit, offset — so one tool
covers both "list everything" and "get one by id"):
list_trademarks — trademarks in the org. Filter by id, name, etc.
list_filings — filings, one row per trademark × office. Carries status,
dates, and deadline fields (expiry_date, renewal_date,
renewal_status). Filter by trademark_id, office_id, status.
list_clients — the org's clients (the entities a trademark belongs to).
list_organisations — the org(s) the key can see (its own; plus managed
orgs for partner/agency keys).
Office actions:
search_office — cross-office search for marks matching a term. Read-only;
results are NOT saved. Args: query (required, ≥2 chars), offices
(optional list of ISO codes like ["EU","DE"] — defaults to a small set),
nice_classes (optional, scope to classes 1-45), limit. The office
fan-out is ONE call, not one per office. Returns results plus
served_from and offices (see "Reading a response" below).
search_conflicts — clearance research. Takes names (a shortlist of up
to 5 candidate names in one call), plus optional nice_classes, offices,
limit. Returns candidates_by_name. Each candidate carries the overlap
signals SEPARATELY: text_similarity, shared_nice_classes,
same_jurisdiction. It returns no verdict and no combined score. Never
produce one yourself — see the guardrail below.
import_filing_from_office — pull a filing from an office by office +
number and save it. Provide EITHER trademark_id (attach to an existing
trademark) OR name + client_id (create a new trademark first). Returns
the imported filing.
refresh_filing_from_office — re-sync a filing's office-sourced fields.
Asynchronous: it enqueues a sync and returns immediately with
sync_status: pending. Re-fetch the filing a moment later to see updates.
Watch (monitoring):
list_watches — the org's active watches, each with the watched filing and
that filing's provenance.
create_watch — start watching a filing. Args: filing_id,
recipient_mode (all_members or specific_user), and
recipient_user_id when the mode is specific_user. A recipient must be a
member of the same organisation; there is no way to notify an outside
address.
update_watch_recipient — change who is notified for an existing watch.
watch_changes_since — poll what changed. Args: since (timestamp of
your last check). Returns only the watches whose filing recorded events
after that moment, each carrying just those new events. An empty result
means nothing changed, NOT that the watch is broken. There is no delete
tool: you can start and re-target a watch but not remove one.
Reading a response (provenance + predictability)
Every record carries a provenance object. Two of its fields change what you
are allowed to say:
served_from — local means MarkMesh served it from its own corpus
(fast, no dependency on the office being up). external means it was
fetched from that office during this call.
citation — has a kind:
office_record → a deep link to that exact record. You may cite it.
office_portal → that office publishes no per-record page; the link is
just its search form. Do not present it as the source of a specific
mark.
unavailable → no public URL is held.
fetched_at — when that data was captured. Use it to tell the user how
fresh the answer is instead of implying it is live.
Cross-office calls also return an offices map: attempted, succeeded,
failed, timed_out.
Common workflows
"What's expiring soon?" → list_filings, then reason over expiry_date
/ renewal_date / renewal_status. Deadlines live on the filing row; there
is no separate deadlines tool.
"Do we already own MARK X?" → list_trademarks (filter by name) and/or
list_filings. For marks NOT yet in the portfolio, search_office.
"Add EU trademark 0181xxxxx for client Acme" →
list_clients to resolve the client's id (or confirm it exists).
import_filing_from_office with office: "EU", number: "0181xxxxx",
and either trademark_id or name + client_id.
- Confirm the returned filing's status/dates back to the user.
"Is NAME safe to use?" → search_conflicts with names (their
shortlist), nice_classes (ask which classes if they haven't said), and
offices. Present candidates grouped by name with their signals and
citations, state which offices failed or timed out, and offer a watch. Do
NOT answer the literal question with yes or no; answer with what exists and
who should judge it.
"Refresh the status of filing Y" → refresh_filing_from_office with the
filing id, then list_filings (filter by that id) after a short pause to
read the updated fields.
Conventions & guardrails
- Confirm before importing.
import_filing_from_office writes to the
portfolio. Echo what you're about to import (office, number, target
trademark/client) and get a nod first, unless the user already said "do it".
- Search before import. If the user gives a fuzzy mark name rather than an
exact application/registration number,
search_office first, show the hits,
let them pick.
- Offices are identified by code (e.g.
EU = EUIPO, DE = DPMA,
US = USPTO). If unsure which office a number belongs to, ask.
- No destructive tools exist in this server — you cannot delete or
overwrite a trademark/filing via MCP. Direct the user to the MarkMesh web
app for edits/deletions.
- Don't fabricate ids. Resolve
trademark_id / client_id via a read
tool; never guess a UUID.
- Check
offices.failed and offices.timed_out before saying anything is
clear. An office that did not answer is NOT an office that found nothing.
Both produce an empty list, and only that map tells them apart. Say "I
couldn't reach the UK register" rather than "no conflicts in the UK".
- Never give a clearance verdict.
search_conflicts deliberately returns
no verdict and no combined score, and you must not synthesise one. Do not
tell a user a name is clear, safe, available, or low-risk, and do not invent
a percentage. Show the candidates, say which signals fired (text similarity,
which classes actually overlap, same territory), name what you could not
check, and leave the judgement to a qualified professional. Clearance turns
on how goods and services are worded, whether a mark is genuinely in use,
and how a particular registry has treated similar marks — none of which this
API returns.
text_similarity is blunt. It is text distance only: no phonetics, no
transliteration, no visual similarity of figurative marks. A low score means
"not textually close", never "no conflict".
- Cite the register, not MarkMesh. Quote
citation.url only when
citation.kind is office_record. Linking five different candidates to one
office search form is not five citations.
- Watch instead of re-running. If a user cares about a mark over time, end
with
create_watch and poll watch_changes_since, rather than telling them
to ask again later. The conflict that matters is often an application
published after the search.
See reference/tools.md for the full argument reference and SETUP.md for
connection setup.
1---2name: markmesh3description: Manage a trademark portfolio through MarkMesh's MCP server — list trademarks, filings and deadlines, run cross-office searches and conflict research for clearance, import or refresh filings from national offices, and register watches that report what changed. Every record carries provenance (source office, fetch time, citable office URL). Use when a user asks about their trademarks, filings, renewal deadlines or clients, wants to search/import a mark from an office (USPTO, EUIPO, DPMA, etc.), wants to check whether a proposed name conflicts with existing marks, or wants to monitor a filing for changes.4license: MIT5---67# MarkMesh — trademark portfolio over MCP89This skill drives the **MarkMesh MCP server**. MarkMesh is a multi-tenant10trademark-management platform; this server exposes a customer's portfolio11(trademarks, filings, deadlines, clients) plus live trademark-office12search/import as MCP tools, scoped to the API key's organisation.1314If the MarkMesh MCP tools are **not** available in this session, the server15isn't configured — point the user to `SETUP.md` (get an API key from the16MarkMesh app, add the connector to Claude Desktop, restart). Don't invent a17local fallback; there is no local data.1819## How auth & scoping work (read this first)2021- Every tool runs as the **API key's organisation**. You only ever see that22 org's data — never assume you can reach another firm's or client's records.23- Two key types: **`mm_live_*`** → real production portfolio;24 **`mm_test_*`** → sandbox. Tell the user which one is active if it25 matters. The sandbox isolates the **portfolio** (trademarks, filings,26 clients, watches), NOT office search: `search_office` and27 `search_conflicts` read the same public register corpus either way, so28 a sandbox search returns real marks. Do not tell a user their sandbox29 search results are fake.30- Calls count against the key's rate limit (live ~300/min, test ~60/min) —31 the same budget as the REST API. Don't poll in tight loops; batch your32 reasoning and make deliberate calls.33- Authorisation is enforced server-side by org policies. A tool returning an34 empty list usually means "nothing in your org matches", not an error.3536## Tools3738**Reads** (each supports `filter`, `sort`, `limit`, `offset` — so one tool39covers both "list everything" and "get one by id"):4041- `list_trademarks` — trademarks in the org. Filter by `id`, `name`, etc.42- `list_filings` — filings, one row per trademark × office. Carries status,43 dates, and **deadline fields** (`expiry_date`, `renewal_date`,44 `renewal_status`). Filter by `trademark_id`, `office_id`, `status`.45- `list_clients` — the org's clients (the entities a trademark belongs to).46- `list_organisations` — the org(s) the key can see (its own; plus managed47 orgs for partner/agency keys).4849**Office actions:**5051- `search_office` — cross-office search for marks matching a term. Read-only;52 results are NOT saved. Args: `query` (required, ≥2 chars), `offices`53 (optional list of ISO codes like `["EU","DE"]` — defaults to a small set),54 `nice_classes` (optional, scope to classes 1-45), `limit`. **The office55 fan-out is ONE call**, not one per office. Returns `results` plus56 `served_from` and `offices` (see "Reading a response" below).57- `search_conflicts` — clearance research. Takes `names` (a shortlist of up58 to 5 candidate names in one call), plus optional `nice_classes`, `offices`,59 `limit`. Returns `candidates_by_name`. Each candidate carries the overlap60 signals SEPARATELY: `text_similarity`, `shared_nice_classes`,61 `same_jurisdiction`. **It returns no verdict and no combined score. Never62 produce one yourself** — see the guardrail below.63- `import_filing_from_office` — pull a filing from an office by `office` +64 `number` and save it. Provide EITHER `trademark_id` (attach to an existing65 trademark) OR `name` + `client_id` (create a new trademark first). Returns66 the imported filing.67- `refresh_filing_from_office` — re-sync a filing's office-sourced fields.68 Asynchronous: it enqueues a sync and returns immediately with69 `sync_status: pending`. Re-fetch the filing a moment later to see updates.7071**Watch (monitoring):**7273- `list_watches` — the org's active watches, each with the watched filing and74 that filing's provenance.75- `create_watch` — start watching a filing. Args: `filing_id`,76 `recipient_mode` (`all_members` or `specific_user`), and77 `recipient_user_id` when the mode is `specific_user`. A recipient must be a78 member of the same organisation; there is no way to notify an outside79 address.80- `update_watch_recipient` — change who is notified for an existing watch.81- `watch_changes_since` — **poll what changed.** Args: `since` (timestamp of82 your last check). Returns only the watches whose filing recorded events83 after that moment, each carrying just those new events. An empty result84 means nothing changed, NOT that the watch is broken. There is no delete85 tool: you can start and re-target a watch but not remove one.8687## Reading a response (provenance + predictability)8889Every record carries a `provenance` object. Two of its fields change what you90are allowed to say:9192- **`served_from`** — `local` means MarkMesh served it from its own corpus93 (fast, no dependency on the office being up). `external` means it was94 fetched from that office during this call.95- **`citation`** — has a `kind`:96 - `office_record` → a deep link to that exact record. **You may cite it.**97 - `office_portal` → that office publishes no per-record page; the link is98 just its search form. **Do not present it as the source of a specific99 mark.**100 - `unavailable` → no public URL is held.101- **`fetched_at`** — when that data was captured. Use it to tell the user how102 fresh the answer is instead of implying it is live.103104Cross-office calls also return an `offices` map: `attempted`, `succeeded`,105`failed`, `timed_out`.106107## Common workflows108109**"What's expiring soon?"** → `list_filings`, then reason over `expiry_date`110/ `renewal_date` / `renewal_status`. Deadlines live on the filing row; there111is no separate deadlines tool.112113**"Do we already own MARK X?"** → `list_trademarks` (filter by name) and/or114`list_filings`. For marks NOT yet in the portfolio, `search_office`.115116**"Add EU trademark 0181xxxxx for client Acme"** →1171. `list_clients` to resolve the client's `id` (or confirm it exists).1182. `import_filing_from_office` with `office: "EU"`, `number: "0181xxxxx"`,119 and either `trademark_id` or `name` + `client_id`.1203. Confirm the returned filing's status/dates back to the user.121122**"Is NAME safe to use?"** → `search_conflicts` with `names` (their123shortlist), `nice_classes` (ask which classes if they haven't said), and124`offices`. Present candidates grouped by name with their signals and125citations, state which offices failed or timed out, and offer a watch. Do126NOT answer the literal question with yes or no; answer with what exists and127who should judge it.128129**"Refresh the status of filing Y"** → `refresh_filing_from_office` with the130filing id, then `list_filings` (filter by that id) after a short pause to131read the updated fields.132133## Conventions & guardrails134135- **Confirm before importing.** `import_filing_from_office` writes to the136 portfolio. Echo what you're about to import (office, number, target137 trademark/client) and get a nod first, unless the user already said "do it".138- **Search before import.** If the user gives a fuzzy mark name rather than an139 exact application/registration number, `search_office` first, show the hits,140 let them pick.141- **Offices are identified by code** (e.g. `EU` = EUIPO, `DE` = DPMA,142 `US` = USPTO). If unsure which office a number belongs to, ask.143- **No destructive tools exist** in this server — you cannot delete or144 overwrite a trademark/filing via MCP. Direct the user to the MarkMesh web145 app for edits/deletions.146- **Don't fabricate ids.** Resolve `trademark_id` / `client_id` via a read147 tool; never guess a UUID.148- **Check `offices.failed` and `offices.timed_out` before saying anything is149 clear.** An office that did not answer is NOT an office that found nothing.150 Both produce an empty list, and only that map tells them apart. Say "I151 couldn't reach the UK register" rather than "no conflicts in the UK".152- **Never give a clearance verdict.** `search_conflicts` deliberately returns153 no verdict and no combined score, and you must not synthesise one. Do not154 tell a user a name is clear, safe, available, or low-risk, and do not invent155 a percentage. Show the candidates, say which signals fired (text similarity,156 which classes actually overlap, same territory), name what you could not157 check, and leave the judgement to a qualified professional. Clearance turns158 on how goods and services are worded, whether a mark is genuinely in use,159 and how a particular registry has treated similar marks — none of which this160 API returns.161- **`text_similarity` is blunt.** It is text distance only: no phonetics, no162 transliteration, no visual similarity of figurative marks. A low score means163 "not textually close", never "no conflict".164- **Cite the register, not MarkMesh.** Quote `citation.url` only when165 `citation.kind` is `office_record`. Linking five different candidates to one166 office search form is not five citations.167- **Watch instead of re-running.** If a user cares about a mark over time, end168 with `create_watch` and poll `watch_changes_since`, rather than telling them169 to ask again later. The conflict that matters is often an application170 published after the search.171172See `reference/tools.md` for the full argument reference and `SETUP.md` for173connection setup.