RISE & AI Sweden — Public MCP

A public MCP server that indexes AI-relevant publications from RISE and AI Sweden — Sweden's two government-funded AI organizations. Provided in good faith to support the growth of the agentic AI ecosystem.

v202606120500Published June 12, 2026·Developing version, constantly in progress

Add it to your AI assistant

In most modern MCP-compatible tools, this URL is all you need. No login, no API key, no authentication.

Server URL
https://rise-ai-sweden.jardenberg.org/api/mcp
Suggested name
rise-ai-sweden
Authentication
None
2,152
Documents indexed
6,300
Searchable chunks

Where to add it

These menus change often — if something looks different, search the app's settings for “MCP”.

Claude Desktop
Settings → Developer → Edit Config, then add an entry under mcpServers with the URL above.
Claude.ai (web)
Customize → Connectors → + → Add custom connector → paste the URL.
ChatGPT (Pro/Team)
Settings → Connectors → Add → MCP server → paste the URL.
Cursor
Settings → MCP → Add new server → paste the URL.
Codex CLI / others
Add an entry to your mcpServers config pointing at the URL.

How to use it in a chat

Once added, just mention the name in your prompt. For example:

“Use rise-ai-sweden to give me the most important content related to Helsingborg.”

JSON config (for tools that need it)

{
  "mcpServers": {
    "rise-ai-sweden": {
      "transport": { "type": "http", "url": "https://rise-ai-sweden.jardenberg.org/api/mcp" }
    }
  }
}

Rate limit: 60 requests / 5 minutes per IP.

Tools exposed

Six tools, each returning JSON. Most accept a page_type filter (event · news · project · page). Examples below show the actual shape your assistant receives.

search_swedish_ai

Hybrid (semantic + lexical) search across all indexed RISE and AI Sweden content. Vector arm for topical queries; lexical arm (Swedish/English stemming + trigram fallback) for proper nouns and short keyword queries. Reciprocal-rank-fusion merge; lexical weighted 2x when query is ≤2 tokens.

Parameters
{
  query: string,                                     // 2–500 chars
  source?:    "rise" | "ai_sweden",
  lang?:      "en" | "sv",
  page_type?: "event" | "news" | "project" | "page",
  limit?:     number                                 // 1–50, default 20
}
Example response
{
  "query": "Helsingborg",
  "count": 2,
  "hybrid": { "rrfK": 60, "weights": { "vector": 1, "lexical": 2 }, "tokenCount": 1 },
  "results": [
    {
      "url": "https://www.ai.se/en/sector-initiatives-projects/.../national-city-lab",
      "title": "National City Lab",
      "source": "ai_sweden",
      "sourceName": "AI Sweden",
      "lang": "en",
      "pageType": "project",
      "score": 0.0312,
      "arms": { "vector": 0.4912, "lexical": 0.0821 },
      "snippet": "The National City Lab in Helsingborg...",
      "fetchedAt": "2026-06-10T08:14:22Z"
    },
    { "...": "..." }
  ]
}

find_mentions

Lexical 'everything that mentions X' primitive. No embeddings — stemmed tsquery + exact-substring fallback. Includes a total field that mirrors a direct count(DISTINCT id) WHERE raw_markdown ILIKE '%term%' SQL query.

Parameters
{
  term: string,                                      // 1–200 chars
  source?:    "rise" | "ai_sweden",
  lang?:      "en" | "sv",
  page_type?: "event" | "news" | "project" | "page",
  limit?:     number                                 // 1–100, default 25
}
Example response
{
  "term": "Helsingborg",
  "total": 39,
  "totalNote": "Exact-substring document count (ILIKE) matching the same filters. Reconciles with raw SQL.",
  "returned": 25,
  "results": [
    {
      "url": "https://www.ai.se/en/news/helsingborg-opens-national-city-lab",
      "title": "Helsingborg opens the National City Lab",
      "source": "ai_sweden",
      "sourceName": "AI Sweden",
      "lang": "en",
      "pageType": "news",
      "matchMode": "exact",
      "rank": 0.0912,
      "snippet": "Helsingborg opens the National City Lab...",
      "fetchedAt": "2026-06-09T07:32:10Z"
    },
    { "...": "..." }
  ]
}

list_latest

Cheap 'what's new' view. Without arguments, returns the newest documents across both sources. Pass source / page_type to slice. No snippets — lightweight metadata only.

Parameters
{
  source?:    "rise" | "ai_sweden",
  lang?:      "en" | "sv",
  page_type?: "event" | "news" | "project" | "page",
  limit?:     number                                 // 1–50, default 20
}
Example response
{
  "count": 2,
  "results": [
    {
      "url": "https://www.ai.se/en/news/...",
      "title": "New language model release",
      "source": "ai_sweden",
      "sourceName": "AI Sweden",
      "lang": "en",
      "pageType": "news",
      "publishedAt": "2026-06-09T00:00:00Z",
      "publishedAtSource": "meta",
      "sitemapLastmod": "2026-06-09T00:00:00Z",
      "fetchedAt": "2026-06-10T08:14:22Z"
    },
    { "...": "..." }
  ]
}

find_similar

Given a URL already in the index, return semantically nearest other documents. Uses the seed document's centroid embedding (average of all its chunks) so navigation chrome doesn't dominate matches. Great for 'more like this' after picking a hit. URL must match exactly — trailing slashes or query strings will miss.

Parameters
{
  url: string,             // a URL from search_swedish_ai / list_latest
  source?: "rise" | "ai_sweden",
  lang?:   "en" | "sv",
  limit?:  number          // 1–25, default 10
}
Example response
{
  "seedUrl": "https://www.ri.se/en/what-we-do/projects/edge-ai-...",
  "count": 2,
  "results": [
    {
      "url": "https://www.ri.se/en/what-we-do/projects/tinyml-...",
      "title": "TinyML for industrial sensors",
      "source": "rise",
      "sourceName": "RISE",
      "lang": "en",
      "score": 0.7912,
      "snippet": "Running compact ML models on microcontrollers...",
      "fetchedAt": "2026-06-07T11:02:08Z"
    },
    { "...": "..." }
  ]
}

get_document

Fetch full cleaned markdown for a single indexed URL. Use after search_swedish_ai to load complete context on the best hit. Body is capped at 80 000 chars — check `truncated` before assuming you have the whole document. `contentNote` / `extractionMethod` surface provenance (e.g. Firecrawl OCR for image-only PDFs, manually replaced stored copies).

Parameters
{ url: string }
Example response
{
  "url": "https://www.ai.se/en/project/...",
  "title": "Project title",
  "lang": "en",
  "pageType": "project",
  "contentType": "html",
  "source": "ai_sweden",
  "sourceName": "AI Sweden",
  "publishedAt": "2026-05-14T00:00:00Z",
  "publishedAtSource": "meta",
  "fetchedAt": "2026-06-08T09:01:44Z",
  "bytesReplacedAt": null,
  "extractionMethod": null,
  "contentNote": null,
  "content": "# Project title\n\nFull markdown body...",
  "truncated": false
}

list_sources

Discover scope and freshness: which sources are indexed, document counts, language breakdown, and the most recent fetch per source.

Parameters
{}
Example response
{
  "sources": [
    {
      "slug": "rise",
      "name": "RISE",
      "rootUrl": "https://www.ri.se",
      "documents": 412,
      "languages": { "en": 280, "sv": 132 },
      "lastUpdated": "2026-06-10T08:14:22Z"
    },
    {
      "slug": "ai_sweden",
      "name": "AI Sweden",
      "rootUrl": "https://www.ai.se",
      "documents": 388,
      "languages": { "en": 250, "sv": 138 },
      "lastUpdated": "2026-06-10T07:55:01Z"
    }
  ]
}

FAQ

Is this open source?
Yes — code lives at github.com/jardenberg/swedish-ai-unlocked. Issues and PRs welcome.
Do I need an API key?
No. Public endpoint, no auth. Rate limit: 60 requests / 5 minutes per IP.
What's indexed?
Public web pages and PDFs from ri.se and ai.se. No paywalled or internal content. Use list_sources for current counts and the most recent fetch per source.
How fresh is it?
Sitemaps are re-checked daily. New documents are scraped, cleaned, chunked, and embedded in the same pass.
Why does find_mentions return fewer rows than `total`?
total is a reconciliation count — distinct documents whose markdown contains the exact substring, matching a direct SQL ILIKE query. returned is what the tool hands back, capped by limit (max 100).
Why doesn't my AI Sweden event URL show up?
Many ai.se event pages 301-redirect to third-party sites (Invajo, Meetup, etc.). Those are deliberately skipped — the index only stores content served from ri.se and ai.se themselves.
How short-query search works
For queries of ≤2 tokens, the lexical arm is weighted 2× over the vector arm. Good for proper nouns and organization names; if a one-word topical query feels too literal, add a second word.
Can I trust the dates?
publishedAt comes from page metadata or PDF path when available, falling back to sitemap last-modified.publishedAtSource tells you which (meta · path · sitemap).
Why does a PDF look OCR'd?
Image-only PDFs and oversized files (~>20 MB) are routed through Firecrawl OCR. get_document surfaces this via extractionMethod: "firecrawl" and a human-readable contentNote.
What does page_type mean?
It's URL-derived, not editorial. project means the URL lives under a /projects/ path, not that someone curated it as a project.