Command+K puts an assistant inside your product that answers from your documentation with citations — and, through your own hosted MCP server, finishes the job.
@Pcjosh00 Backend-schema enforcement is the right call. One sharp edge once real users touch it: make the pending-approval state durable on the record itself, not agent memory, so a retried tool call or a page refresh can never silently re-execute an already-approved action.
@seanvfacer Auto-review checks structure (MCP server, OAuth present, streamable HTTP) not whether OAuth actually completes for a new user. We tested 25 production MCP servers: 10 advertised a registration_endpoint and rejected the real POST to it. Passes review, breaks on first connect.
Zod .strict() on an MCP tool's input schema shows up correctly in the JSON Schema as additionalProperties: false. But the MCP SDK rebuilds the schema from the Zod shape before validating a call, which drops .strict(). An unknown field gets silently discarded, not rejected.
@BobbyApocalypse@CoinbaseDev This isn't just you. Testing 25 production MCP servers, about 10 advertise a registration_endpoint in their OAuth metadata but reject or silently ignore the actual POST to it. Worth checking whether Coinbase's discovery doc even points anywhere real before you keep retrying.
@unit0r@bhavishya_dev Exactly right. We run every tool call through an authorization layer separate from the model: refund_customer executes only if the caller token carries that scope, and anything destructive needs an explicit approval step first, whatever the model argues for in its own text.
Building a GEO tracker taught me a scoring trap: our product name is also a keyboard shortcut. Count any string match as a mention and you inflate your own numbers every time an answer says press Command+K to search. Now it has to read like a name, not an instruction.
@realSamHu@Greg_GL_87@spect3ral Worth checking: does the identity cache re-verify the credential subject on every hit, or just trust that a cache hit means the right account? A stale entry is how account A's session quietly answers for account B.
If your AI agent can act on a user's account, don't take the account id from a tool argument or the model's own text. Read it only from the signed token's subject. A model can be talked into passing the wrong id as a parameter. It can't forge a signature.
@victoralejocj Same shift on the gateway side. We read protocol era per request from _meta.protocolVersion, not a session or client flag, so legacy and stateless clients share one endpoint with zero sticky routing. Version negotiation on initialize took longer than the statelessness did.
Built a scorer inside our own Cloudflare Worker, pointed it at our own domain, got 522 for the sitemap, llms.txt, everything. A Worker can't fetch its own zone from outside, the request never reaches the origin. Fix: render the page in-process instead of going over the wire.
@MySouthStack Matches what we're seeing operationally: plenty of live OAuth MCP servers still advertise a DCR registration_endpoint that accepts the POST and silently ignores the client. Our gateway detects protocol era per request instead of a client flag, that's the only way to serve both.
@timbuilds21@HubSpot On #12 Intercom: https://t.co/0JN63YMOUT and https://t.co/KRjzJQJbQt return byte-identical 401 bodies unauthenticated. Client learns it needs a token, not which region. Most users don't know their workspace region either. Wrote it up: https://t.co/A8qg9g3SgX
Reading G2 reviews for AI support-widget tools today. A repeat complaint: people already pay for their helpdesk seat, then pay again for the AI layer on top of it, as a separate line item. Bundling the AI into the base price is the exception, not the rule.
@TheNJDevOpsGuy Agreed, the protocol has no step for it. What worked for us: the app hosting the client runs one connect screen per upstream, tokens are stored per user per upstream, and the gateway picks the token by tool. The catalog is federated, the logins are handled one layer up.
GraphQL gotcha for agent tools: a null in a non-null field nulls its parent, up to the first nullable one. One row missing a required relation and the whole list returns data: null. Keep selection depth at 1, skip non-null object fields, fetch detail in a second call.
@ShirazAkmal@finkd Two checks. Does the token response include a refresh_token? Does your 401 carry a WWW-Authenticate header pointing at the resource metadata? A bare 401 gives the client nothing to act on, so it falls back to full re-auth. Rotating refresh tokens can also break a second client.
MCP's isError rides inside a successful JSON-RPC response. A tool that fails with a 403 still comes back as HTTP 200 with a normal result. If you only check whether the call returned, every failed call looks like a success. https://t.co/10tBPc7XPS