<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: michielinksee</title>
    <description>The latest articles on DEV Community by michielinksee (@michielinksee).</description>
    <link>https://dev.to/michielinksee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3857701%2F93954c79-a1c4-4f84-a326-713dbd871954.png</url>
      <title>DEV Community: michielinksee</title>
      <link>https://dev.to/michielinksee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michielinksee"/>
    <language>en</language>
    <item>
      <title>5 ways SaaS products lock out AI agents — data from probing 11,000+ services</title>
      <dc:creator>michielinksee</dc:creator>
      <pubDate>Wed, 15 Jul 2026 05:33:47 +0000</pubDate>
      <link>https://dev.to/michielinksee/5-ways-saas-products-lock-out-ai-agents-data-from-probing-11000-services-5dic</link>
      <guid>https://dev.to/michielinksee/5-ways-saas-products-lock-out-ai-agents-data-from-probing-11000-services-5dic</guid>
      <description>&lt;p&gt;Your AI agent isn't dumb. The SaaS it's calling is hostile.&lt;/p&gt;

&lt;p&gt;We run a database that catalogs 11,000+ MCP servers and SaaS APIs, and we probe them — real JSON-RPC handshakes, real liveness checks, real robots.txt reads. &lt;strong&gt;1 in 10 cataloged endpoints was simply dead. 1 in 5 live MCP endpoints failed a basic handshake.&lt;/strong&gt; And that's before your agent even gets to read the docs.&lt;/p&gt;

&lt;p&gt;Here's what the data says about &lt;em&gt;why&lt;/em&gt; agents fail — and it's mostly not the agent's fault.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;1,154 of 11,151 cataloged MCP/API endpoints were &lt;strong&gt;dead&lt;/strong&gt; (removed after our liveness sweep)&lt;/li&gt;
&lt;li&gt;892 of 4,367 live JSON-RPC &lt;code&gt;initialize&lt;/code&gt; probes &lt;strong&gt;failed the handshake&lt;/strong&gt; (20.4%)&lt;/li&gt;
&lt;li&gt;In a deep-dive of 31 major Japanese SaaS products: only &lt;strong&gt;10 ship an official MCP server&lt;/strong&gt;, and &lt;strong&gt;5 have no publicly reachable developer docs at all&lt;/strong&gt; — a human can email sales for the PDF; an agent can't&lt;/li&gt;
&lt;li&gt;One vendor ships an official MCP server &lt;em&gt;while its API documentation site blocks every bot via robots.txt&lt;/em&gt;. The front door is open; the information desk is locked&lt;/li&gt;
&lt;li&gt;Auth is a dialect zoo: custom token headers, non-standard &lt;code&gt;Authorization: Token&lt;/code&gt; schemes, client-ID-to-Bearer exchanges — each one burns tokens on trial-and-error&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. One in ten endpoints is just... dead
&lt;/h2&gt;

&lt;p&gt;Registries and awesome-lists keep growing, but nobody prunes them. When we swept our full catalog of 11,151 MCP/API endpoints with liveness checks, &lt;strong&gt;1,154 (10.4%) were dead&lt;/strong&gt; — servers gone, repos abandoned, URLs 404ing.&lt;/p&gt;

&lt;p&gt;For a human developer this is a mild annoyance. For an agent it's worse: it &lt;em&gt;confidently&lt;/em&gt; selects a tool from a registry, tries to connect, fails, retries, and burns your tokens doing it. Dead endpoints don't look dead in a catalog.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. One in five live MCP endpoints fails the handshake
&lt;/h2&gt;

&lt;p&gt;We send real JSON-RPC &lt;code&gt;initialize&lt;/code&gt; requests to hosted MCP endpoints — the most basic "hello, are you an MCP server?" check.&lt;/p&gt;

&lt;p&gt;Out of 4,367 probe attempts: &lt;strong&gt;3,475 succeeded, 892 failed (20.4%)&lt;/strong&gt;. These aren't dead servers — they respond over HTTP. They just don't complete the protocol handshake: wrong content types, auth walls with no discoverable flow, half-implemented spec versions.&lt;/p&gt;

&lt;p&gt;If a fifth of "live" agent entrances can't say hello, your agent's retry loop isn't a bug. It's the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The docs are locked to humans-only
&lt;/h2&gt;

&lt;p&gt;This one surprised us most. We took 31 major Japanese SaaS products (accounting, HR, e-signature, payments, CRM — the software that runs actual businesses) and verified every fact against vendor primary sources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5 of the 31 had no publicly reachable developer reference at all.&lt;/strong&gt; The API exists — but the spec is behind a sales contact, a partner program, or a paid contract. A human developer emails sales and gets the PDF. An agent hits a marketing page and gives up.&lt;/p&gt;

&lt;p&gt;And the sharpest case: &lt;strong&gt;one major vendor ships an official MCP server while its API documentation site returns 403 to every bot and disallows all crawlers in robots.txt.&lt;/strong&gt; The agent is &lt;em&gt;invited in&lt;/em&gt; and then &lt;em&gt;locked out of the manual&lt;/em&gt;. (Full teardown coming in our next report.)&lt;/p&gt;

&lt;p&gt;If your docs aren't reachable by an agent, then as far as agents are concerned, &lt;strong&gt;your product doesn't exist&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Official agent entrances are still rare
&lt;/h2&gt;

&lt;p&gt;Of those 31 major SaaS products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10 ship an official MCP server&lt;/strong&gt; (accounting leads: freee and Money Forward both AAA in our index)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10 serve an llms.txt&lt;/strong&gt; on their product or developer domain&lt;/li&gt;
&lt;li&gt;The rest offer "an API" — which in agent terms means: figure out auth, pagination, and error semantics yourself, one failed call at a time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We rated all 26 rateable products AAA–D and published the full table, the scoring formula, and the facts behind every grade. It's here: &lt;a href="https://kansei-link.com/agent-readiness-index.html" rel="noopener noreferrer"&gt;Agent Readiness Index 2026 Summer&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Auth is a dialect zoo
&lt;/h2&gt;

&lt;p&gt;Among just these 31 products we found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth 2.0 (fine!)&lt;/li&gt;
&lt;li&gt;API keys in custom headers&lt;/li&gt;
&lt;li&gt;A proprietary &lt;code&gt;Kaonavi-Token&lt;/code&gt; header you get via a client-credentials exchange&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Authorization: Token {token}&lt;/code&gt; — not Bearer, &lt;em&gt;Token&lt;/em&gt; — after a Basic-auth token issuance&lt;/li&gt;
&lt;li&gt;A client-ID→access-token exchange with 1-hour expiry&lt;/li&gt;
&lt;li&gt;An API key &lt;strong&gt;and&lt;/strong&gt; an API token required &lt;em&gt;simultaneously&lt;/em&gt; in different headers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are wrong individually. But every non-standard dialect is another way for an agent to fail silently, retry, and burn tokens. Standardization is a feature; every deviation is a tax on every agent that ever connects.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we measured (and what we don't publish)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Liveness + handshake data&lt;/strong&gt;: our own automated probes (JSON-RPC &lt;code&gt;initialize&lt;/code&gt; against hosted MCP endpoints), continuously since 2026. Counts above are as of 2026-07.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 31-product deep-dive&lt;/strong&gt;: every fact (official MCP, public docs, auth method) verified against vendor primary sources — developer docs, press releases, official help — on 2026-07-13. Corrections welcome; we publish a correction log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What we don't publish&lt;/strong&gt;: per-vendor success-rate numbers. Our third-party telemetry isn't at a scale where those numbers would be fair yet, so they stay unpublished until it is. Methodology and independence policy are public: &lt;a href="https://kansei-link.com/independence.html" rel="noopener noreferrer"&gt;kansei-link.com/independence&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dataset behind this is what our MCP server serves to agents (connection guides, auth pitfalls, failure workarounds for 11,000+ services): &lt;code&gt;npx @kansei-link/mcp-server&lt;/code&gt; — free, and every failure report makes the data better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the worst API your agent has ever fought with?&lt;/strong&gt; Dead endpoint, undocumented auth dialect, docs behind a sales call — war stories welcome. We're collecting failure patterns for the next report.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written with AI assistance; all measurements, verification, and analysis are our own. Data: KanseiLink, measured 2026-07.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>showdev</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Stop letting Claude guess your SaaS API auth flow</title>
      <dc:creator>michielinksee</dc:creator>
      <pubDate>Wed, 01 Jul 2026 13:37:29 +0000</pubDate>
      <link>https://dev.to/michielinksee/stop-letting-claude-guess-your-saas-api-auth-flow-36p3</link>
      <guid>https://dev.to/michielinksee/stop-letting-claude-guess-your-saas-api-auth-flow-36p3</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Claude Code is great at writing integration code.&lt;/p&gt;

&lt;p&gt;But when I ask it to connect to a SaaS API, the same annoying pattern keeps showing up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write auth code
↓
Call the API
↓
Auth error
↓
Fix the scope
↓
Missing required parameter
↓
Fix again
↓
Wrong endpoint version
↓
Try again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the time it works, I have burned thousands of tokens.&lt;/p&gt;

&lt;p&gt;This happens a lot with SaaS APIs like Salesforce, HubSpot, Stripe, Slack, freee, SmartHR, kintone, and others.&lt;/p&gt;

&lt;p&gt;The issue is not that Claude cannot write code.&lt;/p&gt;

&lt;p&gt;The issue is that Claude often starts with stale assumptions.&lt;/p&gt;

&lt;p&gt;SaaS APIs change all the time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth flows get updated&lt;/li&gt;
&lt;li&gt;PKCE becomes required&lt;/li&gt;
&lt;li&gt;API versions change&lt;/li&gt;
&lt;li&gt;required parameters get added&lt;/li&gt;
&lt;li&gt;rate limits change&lt;/li&gt;
&lt;li&gt;official docs get reorganized&lt;/li&gt;
&lt;li&gt;MCP servers behave differently from direct API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the agent starts with the wrong connection assumptions, everything after that becomes a retry loop.&lt;/p&gt;

&lt;p&gt;So I tried a simple fix:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before letting Claude write API integration code, give it a connection guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;Instead of asking Claude to connect directly to a SaaS API, I added an MCP server that tells Claude how to connect first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add kansei-link &lt;span class="nt"&gt;--&lt;/span&gt; npx @kansei-link/mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key.&lt;br&gt;&lt;br&gt;
No auth.&lt;br&gt;&lt;br&gt;
No setup beyond that.&lt;/p&gt;

&lt;p&gt;Now the flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before:
User → Claude → SaaS API
              ↑
        guessing from stale knowledge

After:
User → Claude → KanseiLINK MCP → connection guide
              ↓
           SaaS API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is not to make Claude “smarter”.&lt;/p&gt;

&lt;p&gt;The goal is to stop Claude from guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Salesforce
&lt;/h2&gt;

&lt;p&gt;Before writing code, Claude can ask KanseiLINK what it should know about the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search_services({ query: "salesforce crm" })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Salesforce
- Grade: BB
- Agent connection success rate: 43%
- Connection type: third-party MCP / API
- Auth: OAuth 2.0
- Known issues:
  - complex scope configuration
  - instance URL varies by org
  - API version must be specified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it can ask for the actual connection details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lookup({ service_id: "salesforce-crm", detail: true })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Auth:
  OAuth 2.0

Common pitfalls:
  - instance URL varies per org
  - API version must be specified
  - third-party MCP servers may not support all write operations
  - Bulk API has different requirements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That context is small, but it changes the output a lot.&lt;/p&gt;

&lt;p&gt;Claude starts from the right assumptions instead of writing a plausible but outdated integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: freee accounting
&lt;/h2&gt;

&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lookup({ service_id: "freee-accounting", detail: true })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Auth:
  OAuth 2.0 + PKCE

Required:
  company_id

Common pitfalls:
  - PKCE is required
  - company_id must be fetched before posting transactions
  - endpoint versions are easy to confuse
  - missing scopes cause auth failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly the kind of information that prevents a 3-turn debugging loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before vs after
&lt;/h2&gt;

&lt;p&gt;I tested this on a few common SaaS integration tasks.&lt;/p&gt;

&lt;p&gt;This is not a formal benchmark, but I tracked token usage and retries in my own Claude Code workflow.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Reduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Salesforce opportunity update&lt;/td&gt;
&lt;td&gt;~5,500 tokens&lt;/td&gt;
&lt;td&gt;~1,800 tokens&lt;/td&gt;
&lt;td&gt;67%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HubSpot contact creation&lt;/td&gt;
&lt;td&gt;~3,400 tokens&lt;/td&gt;
&lt;td&gt;~1,200 tokens&lt;/td&gt;
&lt;td&gt;65%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stripe invoice generation&lt;/td&gt;
&lt;td&gt;~2,800 tokens&lt;/td&gt;
&lt;td&gt;~1,100 tokens&lt;/td&gt;
&lt;td&gt;61%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack webhook setup&lt;/td&gt;
&lt;td&gt;~2,100 tokens&lt;/td&gt;
&lt;td&gt;~900 tokens&lt;/td&gt;
&lt;td&gt;57%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On average, this reduced token usage by around &lt;strong&gt;60–70%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The savings mostly came from removing failed retries.&lt;/p&gt;

&lt;p&gt;The lookup itself is cheap.&lt;br&gt;&lt;br&gt;
A failed retry is expensive.&lt;/p&gt;
&lt;h2&gt;
  
  
  The MCP tools
&lt;/h2&gt;

&lt;p&gt;KanseiLINK MCP currently exposes three simple tools.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. search_services
&lt;/h3&gt;

&lt;p&gt;Use this to find the right service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search_services({ query: "accounting invoice" })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;freee: AAA grade, high success rate, API/MCP support
QuickBooks: A grade, API-first
Xero: BBB grade, community MCP available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The useful part is that services are ranked by how easy they are for agents to actually connect to.&lt;/p&gt;

&lt;p&gt;Not by marketing claims.&lt;br&gt;&lt;br&gt;
Not by popularity.&lt;br&gt;&lt;br&gt;
By agent connection signals.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. lookup
&lt;/h3&gt;

&lt;p&gt;Use this before writing code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lookup({ service_id: "freee-accounting", detail: true })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Auth:
  OAuth 2.0 + PKCE

Rate limit:
  300 requests / 5 min

Required:
  company_id

Gotchas:
  - PKCE is mandatory
  - company_id must be fetched first
  - some endpoint versions are easy to confuse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the main value.&lt;/p&gt;

&lt;p&gt;Claude gets the connection map before it starts coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. report
&lt;/h3&gt;

&lt;p&gt;Optional, but useful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;report({
  service_id: "freee-accounting",
  success: true
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;report({
  service_id: "freee-accounting",
  success: false,
  reason: "OAuth scope mismatch"
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps improve the connection data over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just read the docs?
&lt;/h2&gt;

&lt;p&gt;You should read the docs.&lt;/p&gt;

&lt;p&gt;But when working with coding agents, there are three practical problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Model knowledge is stale
&lt;/h3&gt;

&lt;p&gt;Claude or GPT may know an older version of an API.&lt;/p&gt;

&lt;p&gt;That is enough to cause a bad first implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Docs are long
&lt;/h3&gt;

&lt;p&gt;The answer might be in the docs, but buried across multiple pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auth&lt;/li&gt;
&lt;li&gt;scopes&lt;/li&gt;
&lt;li&gt;rate limits&lt;/li&gt;
&lt;li&gt;object IDs&lt;/li&gt;
&lt;li&gt;endpoint versions&lt;/li&gt;
&lt;li&gt;sandbox behavior&lt;/li&gt;
&lt;li&gt;write permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you make the agent read everything from scratch, you may burn tokens before writing any useful code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. MCP-specific issues are not in vendor docs
&lt;/h3&gt;

&lt;p&gt;This is the biggest one.&lt;/p&gt;

&lt;p&gt;A direct API call may work, but an MCP server may fail because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the MCP server is outdated&lt;/li&gt;
&lt;li&gt;only read operations are supported&lt;/li&gt;
&lt;li&gt;write operations have lower success rates&lt;/li&gt;
&lt;li&gt;OAuth scopes are handled differently&lt;/li&gt;
&lt;li&gt;the server wraps the API in a non-obvious way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vendor docs usually do not cover that.&lt;/p&gt;

&lt;p&gt;Agent connection data does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it covers
&lt;/h2&gt;

&lt;p&gt;KanseiLINK currently includes connection data for 11,000+ SaaS and API services.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Accounting:
  freee
  QuickBooks
  Xero
  MYOB

CRM:
  Salesforce
  HubSpot
  Sansan

HR:
  BambooHR
  SmartHR
  Gusto

Dev tools:
  GitHub
  GitLab
  Jira
  Linear

Other:
  Slack
  Notion
  Stripe
  Twilio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each service has a grade from AAA to C.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AAA: likely to work smoothly
A: usable with minor care
BBB: some friction expected
BB: expect issues
C: difficult to connect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a rating of the product.&lt;/p&gt;

&lt;p&gt;It is a rating of how easy it is for an AI agent to discover, understand, connect, and execute against that service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add kansei-link &lt;span class="nt"&gt;--&lt;/span&gt; npx @kansei-link/mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Desktop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"kansei-link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@kansei-link/mcp-server"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/kansei-link/kansei-mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;When Claude Code struggles with SaaS API integration, the problem is often not code generation.&lt;/p&gt;

&lt;p&gt;It is the starting context.&lt;/p&gt;

&lt;p&gt;If the agent starts with stale API assumptions, you pay for retries.&lt;/p&gt;

&lt;p&gt;If the agent starts with a current connection guide, it writes better code sooner.&lt;/p&gt;

&lt;p&gt;That is the whole trick:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give the agent the map before asking it to drive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are using Claude Code, Cursor, or any AI coding agent for SaaS API integration, this can save real tokens and real time.&lt;/p&gt;

</description>
      <category>api</category>
      <category>claude</category>
      <category>llm</category>
      <category>saas</category>
    </item>
    <item>
      <title>I let AI build my products for months — then I couldn't tell what any of them were anymore</title>
      <dc:creator>michielinksee</dc:creator>
      <pubDate>Tue, 16 Jun 2026 08:11:45 +0000</pubDate>
      <link>https://dev.to/michielinksee/ai-didnt-slow-my-products-down-it-drifted-them-off-course-faster-so-i-built-an-intent-datadog-2a5g</link>
      <guid>https://dev.to/michielinksee/ai-didnt-slow-my-products-down-it-drifted-them-off-course-faster-so-i-built-an-intent-datadog-2a5g</guid>
      <description>&lt;p&gt;Claude Code and Cursor make you ship fast.&lt;/p&gt;

&lt;p&gt;But once I was running &lt;strong&gt;several products in parallel&lt;/strong&gt; — and across &lt;strong&gt;several different LLMs&lt;/strong&gt; (Claude Code, Cursor, ChatGPT) — a different problem showed up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I'd forget what I'd decided (the human)&lt;/li&gt;
&lt;li&gt;A design I locked in via Claude Code, the Cursor session didn't know about (the LLM)&lt;/li&gt;
&lt;li&gt;The README and the code drifted apart&lt;/li&gt;
&lt;li&gt;The CLI changed, but npm and the docs stayed old&lt;/li&gt;
&lt;li&gt;Neither I nor the AI could say which part of the product we were even touching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every single change was correct. But the product as a whole kept sliding away from what it was supposed to be.&lt;/p&gt;

&lt;p&gt;That's rough.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Building just one product? &lt;code&gt;CLAUDE.md&lt;/code&gt; is probably enough. This is for people juggling several.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's a name for this now: &lt;strong&gt;intent drift&lt;/strong&gt; — the product slowly diverging from what you meant to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The exact moment it bites
&lt;/h2&gt;

&lt;p&gt;You ask Claude Code:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;fix the CLI setup flow&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does. Perfectly.&lt;/p&gt;

&lt;p&gt;But to actually match that change, you probably also needed to touch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README&lt;/li&gt;
&lt;li&gt;the npm description&lt;/li&gt;
&lt;li&gt;the GitHub install steps&lt;/li&gt;
&lt;li&gt;docs&lt;/li&gt;
&lt;li&gt;the landing page&lt;/li&gt;
&lt;li&gt;the demo screenshot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI fixes the spot you asked about. That's it.&lt;/p&gt;

&lt;p&gt;So you get:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The engine is fine. The install steps are stale. Users get stuck.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's scarier than a bug. The code runs — the &lt;em&gt;story around it&lt;/em&gt; is wrong.&lt;/p&gt;

&lt;p&gt;Here's the tool catching exactly that — the README promises a &lt;code&gt;--export&lt;/code&gt; flag the code doesn't have, and it shows the blast radius too:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F299iwgcvc2il43jjqh54.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F299iwgcvc2il43jjqh54.gif" alt="Linksee catching that the README's --export flag is missing from the code, with the blast radius"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A product has a map
&lt;/h2&gt;

&lt;p&gt;A product grows along a path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;discovered → understood → tried → installed → kept → paid → expanded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And under each step sits a stack of surfaces:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LP / README / npm / GitHub / CLI / MCP / dashboard / docs / Stripe / support&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While coding, you &lt;em&gt;want&lt;/em&gt; to know: "where on this map am I, and if I change this, what else moves?" But running several products across several LLMs, that map falls out of your head — and nobody is tracking it. That's the drift.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I'm building Linksee Memory
&lt;/h2&gt;

&lt;p&gt;A local-first tool that records the &lt;strong&gt;decisions&lt;/strong&gt;, the &lt;strong&gt;implementation&lt;/strong&gt;, and the &lt;strong&gt;drift&lt;/strong&gt; as you build with AI — so you can see them later.&lt;/p&gt;

&lt;p&gt;It started as a memory tool. Now I think of it differently:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A shared map of the project — for the human and the multiple AIs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. What's drifting?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx linksee-memory map status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lists what's out of sync:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README says it, code doesn't&lt;/li&gt;
&lt;li&gt;CLI changed, docs are old&lt;/li&gt;
&lt;li&gt;LP and README disagree&lt;/li&gt;
&lt;li&gt;a flow you planned, then abandoned&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. What do I fix next?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx linksee-memory map next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Show me the whole map
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx linksee-memory map blueprint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Bonus: &lt;code&gt;npx linksee-memory map where README.md&lt;/code&gt; tells you where a file sits, and what changing it would touch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It all lives in a local SQLite file — so Claude Code, Cursor, ChatGPT, Codex and Gemini share the &lt;strong&gt;same map&lt;/strong&gt;. No cloud, no API key, MIT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it helps
&lt;/h2&gt;

&lt;p&gt;The scariest thing in AI development isn't the code breaking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's the code working while the product's story — install, docs, promises — quietly drifts.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx linksee-memory init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything stays local. Nothing leaves your machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repo: &lt;a href="https://github.com/michielinksee/linksee-memory" rel="noopener noreferrer"&gt;https://github.com/michielinksee/linksee-memory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;landing: &lt;a href="https://linksee-site.vercel.app" rel="noopener noreferrer"&gt;https://linksee-site.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A GitHub star genuinely makes my day 🙏&lt;/p&gt;

&lt;h2&gt;
  
  
  I'd love your take
&lt;/h2&gt;

&lt;p&gt;If you run multiple products / multiple LLMs — have you hit the "wait, what was this even for?" moment?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was it a &lt;em&gt;memory&lt;/em&gt; problem, or a &lt;em&gt;map&lt;/em&gt; problem?&lt;/li&gt;
&lt;li&gt;Of "what's drifting," "what's next," and "the whole map" — which would you actually use?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment, or find me on X (&lt;a href="https://x.com/michielinksee" rel="noopener noreferrer"&gt;@michielinksee&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Solo founder in Singapore, building in public.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I Built an MCP Server to Stop Claude Code from Forgetting Everything Between Sessions</title>
      <dc:creator>michielinksee</dc:creator>
      <pubDate>Fri, 29 May 2026 10:30:27 +0000</pubDate>
      <link>https://dev.to/michielinksee/i-built-an-mcp-server-to-stop-claude-code-from-forgetting-everything-between-sessions-im0</link>
      <guid>https://dev.to/michielinksee/i-built-an-mcp-server-to-stop-claude-code-from-forgetting-everything-between-sessions-im0</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Claude Code starts every session cold. It re-suggests libraries I already rejected, asks &lt;em&gt;"should we use X?"&lt;/em&gt; about decisions made weeks ago, and re-reads unchanged files from scratch (paying full tokens each time).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: I built &lt;a href="https://github.com/michielinksee/linksee-memory" rel="noopener noreferrer"&gt;&lt;code&gt;linksee-memory&lt;/code&gt;&lt;/a&gt; — an MCP server with 6 structured memory layers and chunk-level file diff caching. Local SQLite, MIT, no cloud. Works across Claude Code / Cursor / Codex / Gemini CLI from the same database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The feature that actually changed my workflow&lt;/strong&gt;: the &lt;code&gt;caveat&lt;/code&gt; layer — forget-protected entries for &lt;em&gt;"never do this again"&lt;/em&gt;. Cut repeat-suggestions of bad patterns to &lt;strong&gt;zero&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install&lt;/strong&gt;: &lt;code&gt;npm install -g linksee-memory&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The problem: my agent kept making the same mistake
&lt;/h2&gt;

&lt;p&gt;Three Mondays in a row last month, I explained the same deploy failure to Claude Code. The root cause was identical each time: our production Cloudflare Workers had a memory-cache incoherence issue between distributed instances. Each session, I walked through the same investigation — same files, same logs, same 30-minute trail to the same conclusion.&lt;/p&gt;

&lt;p&gt;Claude Code doesn't remember previous sessions. So every Monday morning, I was re-discovering the same bug with my agent from scratch.&lt;/p&gt;

&lt;p&gt;I tried the available solutions; none fit:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What's good&lt;/th&gt;
&lt;th&gt;Where it fell short for me&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Zero setup, official&lt;/td&gt;
&lt;td&gt;Flat structure, model ignores parts of it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/mem0ai/mem0" rel="noopener noreferrer"&gt;Mem0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Hosted, easy install&lt;/td&gt;
&lt;td&gt;Cloud-only, no "pain memory" concept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/letta-ai/letta" rel="noopener noreferrer"&gt;Letta&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Built into an agent framework&lt;/td&gt;
&lt;td&gt;Can't share memory across MCP clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/getzep/zep" rel="noopener noreferrer"&gt;Zep&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Graph-based, strong relationships&lt;/td&gt;
&lt;td&gt;Single-client; I also use Cursor and Codex&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All good products optimizing for different things. But the one feature I wanted most — &lt;strong&gt;a guarantee that I'll never repeat the same mistake&lt;/strong&gt; — wasn't in any of them.&lt;/p&gt;

&lt;p&gt;So I built &lt;code&gt;linksee-memory&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design: 6 layers, with &lt;code&gt;caveat&lt;/code&gt; as the hero
&lt;/h2&gt;

&lt;p&gt;linksee-memory organizes memory into 6 explicit layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-- goal           Why are we doing this?
+-- context        Current situation &amp;amp; constraints
+-- emotion        User's mood, tone of the relationship
+-- implementation How we built it (success or failure)
+-- caveat         Pain lessons (forget-protected)
+-- learning       Growth log &amp;amp; realizations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key design principle is &lt;strong&gt;WHY-first&lt;/strong&gt;. Other tools store &lt;em&gt;facts&lt;/em&gt; ("we use PostgreSQL"). linksee-memory separates the WHY ("we chose PostgreSQL because the workload is OLTP with strict consistency needs") from the WHAT ("connection pool: 20, timeout: 30s").&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;caveat&lt;/code&gt; layer is special. Entries there are &lt;strong&gt;permanently protected from auto-forgetting&lt;/strong&gt; — even when old memories decay and get consolidated, caveats stay forever. This is how I enforce &lt;em&gt;"never make this mistake again"&lt;/em&gt; as a structural property, not prompt discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 tools, not 8
&lt;/h2&gt;

&lt;p&gt;Early versions had 8 separate tools (&lt;code&gt;remember&lt;/code&gt;, &lt;code&gt;update_memory&lt;/code&gt;, &lt;code&gt;forget&lt;/code&gt;, &lt;code&gt;recall&lt;/code&gt;, &lt;code&gt;recall_file&lt;/code&gt;, &lt;code&gt;list_entities&lt;/code&gt;, &lt;code&gt;consolidate&lt;/code&gt;, &lt;code&gt;read_smart&lt;/code&gt;). This worked fine in Claude Code where I could teach tool selection via SKILL.md.&lt;/p&gt;

&lt;p&gt;But Cursor couldn't tell &lt;code&gt;recall&lt;/code&gt; from &lt;code&gt;recall_file&lt;/code&gt;. Codex mixed up &lt;code&gt;remember&lt;/code&gt; and &lt;code&gt;update_memory&lt;/code&gt;. &lt;strong&gt;Too many tools = LLM tool selection breaks down.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;v0.7 unified everything into 3 tools:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remember&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create, update, or delete a memory. Mode auto-detected from params.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recall&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Search memories, get file history, or list entities. Mode auto-detected from params.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;read_smart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read a file with chunk-level diff caching.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create&lt;/span&gt;
&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;entity_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyProject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;caveat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Update (was: update_memory)&lt;/span&gt;
&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;memory_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;updated content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Delete (was: forget)&lt;/span&gt;
&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;memory_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Search (was: recall)&lt;/span&gt;
&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RLS policy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;caveat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// File history (was: recall_file)&lt;/span&gt;
&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Entity overview (was: list_entities)&lt;/span&gt;
&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One tool name per intent. Every LLM client handles it correctly now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that surprised me: &lt;code&gt;read_smart()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Structured memory is half the tool. The other half is file-diff caching.&lt;/p&gt;

&lt;p&gt;Think about what your agent does at the start of every session:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Re-reads &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Re-reads your main entry file&lt;/li&gt;
&lt;li&gt;Re-reads the config&lt;/li&gt;
&lt;li&gt;Re-reads the tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each file is maybe 500-2000 lines. Each session, you pay full tokens to re-read all of them. But &lt;strong&gt;in most sessions, most of these files haven't changed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;read_smart()&lt;/code&gt; fixes this with chunk-level caching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// First read: full file, chunked and cached&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_smart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/http-server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// -&amp;gt; full content, ~3400 tokens&lt;/span&gt;

&lt;span class="c1"&gt;// Same session, no change: cache hit&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_smart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/http-server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// -&amp;gt; { status: "unchanged", tokens_used: ~50 }&lt;/span&gt;

&lt;span class="c1"&gt;// After editing 2 functions: only changed chunks returned&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_smart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/http-server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// -&amp;gt; only the 2 changed function chunks, ~340 tokens&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chunk boundaries are language-aware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code (TS / JS / Python / etc.)&lt;/strong&gt;: AST-based, one chunk per function or class&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markdown&lt;/strong&gt;: one chunk per &lt;code&gt;h2&lt;/code&gt; / &lt;code&gt;h3&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON / YAML&lt;/strong&gt;: one chunk per top-level key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cache keys are &lt;code&gt;sha256(chunk_content)&lt;/code&gt;. In practice, I see &lt;strong&gt;~86% token reduction&lt;/strong&gt; on file re-reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concrete example: the caveat that stopped Claude from repeating
&lt;/h2&gt;

&lt;p&gt;Here's a real example of &lt;code&gt;caveat&lt;/code&gt; working.&lt;/p&gt;

&lt;p&gt;A few weeks ago, for a one-off data migration task, Claude suggested &lt;em&gt;"let's set up a cron job"&lt;/em&gt;. One-off tasks shouldn't use cron (auth rotation overhead, monitoring cost, retry logic that doesn't match one-off semantics).&lt;/p&gt;

&lt;p&gt;I stored one caveat entry:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't propose cron for one-off tasks. Alternatives: GitHub Actions &lt;code&gt;workflow_dispatch&lt;/code&gt;, or a manual script with a completion notification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the 4 sessions &lt;strong&gt;before&lt;/strong&gt; I added that caveat, Claude suggested cron 4 times for one-off tasks.&lt;/p&gt;

&lt;p&gt;In the 3 weeks &lt;strong&gt;since&lt;/strong&gt;? &lt;strong&gt;Zero.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And because all my LLM clients share the same SQLite file, the caveat also works in Cursor, Codex, and Gemini CLI — not just Claude Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install (2 minutes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; linksee-memory
claude mcp add &lt;span class="nt"&gt;-s&lt;/span&gt; user linksee &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; linksee-memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cursor
&lt;/h3&gt;

&lt;p&gt;Settings -&amp;gt; Features -&amp;gt; "Model Context Protocol" -&amp;gt; Edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"linksee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"linksee-memory"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OpenAI Codex
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex mcp add linksee-memory &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; linksee-memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Gemini CLI
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;~/.gemini/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"linksee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"linksee-memory"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything runs locally. SQLite file at &lt;code&gt;~/.linksee-memory/memory.db&lt;/code&gt;. No cloud, no API key, no telemetry. MIT licensed.&lt;/p&gt;

&lt;p&gt;Because memory lives in a single SQLite file, it's &lt;strong&gt;shared across all MCP clients on your machine&lt;/strong&gt;. My Claude Code sessions and my Cursor sessions see the same memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'd genuinely love feedback
&lt;/h2&gt;

&lt;p&gt;I've been using this daily for 3+ months, and my results are biased by the fact that I designed it for my own workflow. I'd like to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the &lt;code&gt;caveat&lt;/code&gt; layer actually prevent &lt;em&gt;your&lt;/em&gt; agent from repeating mistakes, or am I pattern-matching on one dataset (me)?&lt;/li&gt;
&lt;li&gt;How does the chunk cache behave on your codebase? Monorepos, generated code, notebooks — I'd love bug reports.&lt;/li&gt;
&lt;li&gt;Is 6 layers too many? Too few? Are there memory types you want that none of these cover?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/michielinksee/linksee-memory/issues" rel="noopener noreferrer"&gt;Open an issue on GitHub&lt;/a&gt;, or ping me on X at &lt;a href="https://x.com/ELLECraftsinga1" rel="noopener noreferrer"&gt;@ELLECraftsinga1&lt;/a&gt;. I respond to everything.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/michielinksee/linksee-memory" rel="noopener noreferrer"&gt;https://github.com/michielinksee/linksee-memory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://docs.linksee.app" rel="noopener noreferrer"&gt;https://docs.linksee.app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>claude</category>
      <category>mcp</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built an MCP server that helps agents find and orchestrate other MCP servers</title>
      <dc:creator>michielinksee</dc:creator>
      <pubDate>Thu, 02 Apr 2026 13:19:35 +0000</pubDate>
      <link>https://dev.to/michielinksee/i-built-an-mcp-server-that-helps-agents-find-and-orchestrate-other-mcp-servers-327m</link>
      <guid>https://dev.to/michielinksee/i-built-an-mcp-server-that-helps-agents-find-and-orchestrate-other-mcp-servers-327m</guid>
      <description>&lt;p&gt;The Problem&lt;br&gt;
MCP servers are multiplying fast. There are now MCP servers for accounting (freee), HR (SmartHR), project management (Backlog), messaging (Chatwork, LINE WORKS, Slack), and more — just for Japanese SaaS alone.&lt;/p&gt;

&lt;p&gt;But when you tell an agent "create and send an invoice," it has to figure out:&lt;/p&gt;

&lt;p&gt;Which MCP handles invoices?&lt;br&gt;
How to combine multiple MCPs for a complete workflow?&lt;br&gt;
Has anything changed since last time?&lt;br&gt;
There's no discovery layer. Every agent starts from zero.&lt;/p&gt;

&lt;p&gt;What I Built&lt;br&gt;
An MCP server that searches, combines, and tracks other MCP servers.&lt;/p&gt;

&lt;p&gt;npx @kansei-link/mcp-server&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5fgc78abbvljll1exjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5fgc78abbvljll1exjj.png" alt=" " width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>modelcontextprotocol</category>
      <category>mcp</category>
      <category>ai</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
