Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: [master]
pull_request:

jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run check-types
- run: npm test
# Extension-host smoke in a real VS Code (headless via Xvfb).
- run: xvfb-run -a npm run test:host
- run: npm run compile
- run: npx @vscode/vsce package -o /tmp/agentage.vsix
# Hand the packaged .vsix to the e2e repo's `vscode` integration project.
- uses: actions/upload-artifact@v4
with:
name: agentage-vsix
path: /tmp/agentage.vsix
if-no-files-found: error
37 changes: 37 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Publish

on:
push:
tags:
- 'v*'

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run check-types
- run: npm test
- name: Assert tag matches package.json version
run: test "v$(node -p "require('./package.json').version")" = "${GITHUB_REF_NAME}"
- name: Publish to Open VSX (also produces the .vsix)
id: ovsx
uses: HaaLeo/publish-vscode-extension@v2
with:
pat: ${{ secrets.OPEN_VSX_TOKEN }}
- name: Publish to VS Code Marketplace (reuse the same .vsix)
uses: HaaLeo/publish-vscode-extension@v2
with:
pat: ${{ secrets.VS_MARKETPLACE_TOKEN }}
registryUrl: https://marketplace.visualstudio.com
extensionFile: ${{ steps.ovsx.outputs.vsixPath }}
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "${GITHUB_REF_NAME}" --generate-notes "${{ steps.ovsx.outputs.vsixPath }}"
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
*.vsix
.vscode-test/
*.log
9 changes: 9 additions & 0 deletions .vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from '@vscode/test-cli';

// Runs the host smoke (test-host/**) inside a real downloaded VS Code, loading the
// built extension from ./dist (run `npm run compile` first; `test:host` does).
export default defineConfig({
files: 'test-host/**/*.test.js',
version: 'stable',
mocha: { ui: 'tdd', timeout: 20000 },
});
13 changes: 13 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "npm: compile"
}
]
}
20 changes: 20 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "compile",
"group": "build",
"problemMatcher": [],
"label": "npm: compile"
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"label": "npm: watch"
}
]
}
19 changes: 19 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.vscode/**
.vscode-test/**
.vscode-test.mjs
src/**
test/**
test-host/**
node_modules/**
esbuild.js
tsconfig.json
vitest.config.ts
vitest.config.*
**/*.ts
**/*.map
media/*.svg
media/demo.gif
scripts/**
.gitignore
.github/**
CONTRIBUTING.md
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

All notable changes to the Agentage extension are documented here. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.1] - 2026-06-21

### Added

- **Auto-install on setup** - the Agentage Memory server registers itself with your editor's AI on activation: VS Code via the native MCP provider API (appears in the MCP servers list, no command), Cursor and Windsurf via their config file (idempotent, merged, never clobbered). VS Code runs OAuth itself on first use (one-time trust + sign-in).
- `Agentage: Connect Memory to this editor` - the same registration on demand (manual re-connect / unknown forks; uses the VS Code install deeplink).
- `agentage.mcpUrl` setting to target a different stack.
53 changes: 53 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Contributing

## Develop

```bash
npm install
npm run compile # bundle to dist/extension.js (esbuild)
npm run watch # rebuild on change
npm test # vitest unit tests (pure helpers)
npm run check-types # tsc --noEmit
```

Press **F5** in VS Code to launch the Extension Development Host, then run **`Agentage: Connect Memory to this editor`** from the command palette.

Point at a non-prod stack via the `agentage.mcpUrl` setting before connecting.

## Architecture

The extension registers the remote MCP server (`memory.agentage.io/mcp`) with the
host editor's AI agent - it does not talk to MCP itself, and it has no runtime
dependencies. The host editor runs OAuth 2.1 when its agent first uses the server.

```
src/extension.ts activate(): auto-register (provider + fork config) + the manual command
src/mcp-provider.ts VS Code native MCP provider (onStartupFinished) - server appears with no command
src/connect-editor.ts the manual command + autoConnectForks (silent idempotent Cursor/Windsurf write)
src/connect-core.ts pure helpers (host detect, per-editor JSON, JSONC-safe merge, idempotency check) - vitest-tested
src/config.ts the agentage.mcpUrl setting
```

Auto-install: VS Code is contributed via `contributes.mcpServerDefinitionProviders` + `registerMcpServerDefinitionProvider` (the id must match; activation is `onStartupFinished`). The forks have no such API, so the extension writes their config file directly.

Per-editor config shapes differ - VS Code `servers` + `type:http` + `url`, Cursor
`mcpServers` + `url`, Windsurf `mcpServers` + `serverUrl` - so existing config is
read-merged, never overwritten.

## Package a .vsix

```bash
npx @vscode/vsce package # agentage-<version>.vsix
npx @vscode/vsce ls # confirm only dist/, README, LICENSE, CHANGELOG, icon, package.json ship
code --install-extension agentage-<version>.vsix
```

## Release

Publishing to the VS Code Marketplace and Open VSX is automated by
`.github/workflows/publish.yml`, triggered on a `v*` tag. Bump `version`, update
`CHANGELOG.md`, dogfood the `.vsix` in VS Code and a fork, then:

```bash
git tag v<version> && git push --tags
```
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 agentage

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Agentage

> Connect your editor's AI to your [Agentage](https://memory.agentage.io) memory - over MCP.

[![VS Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/agentage.agentage?label=VS%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage)
[![Open VSX Version](https://img.shields.io/open-vsx/v/agentage/agentage?label=Open%20VSX)](https://open-vsx.org/extension/agentage/agentage)
[![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)

![Copilot Chat answering from your Agentage memory through the MCP connection](https://github.com/agentage/vscode-agentage/raw/master/media/demo.gif)

On install, Agentage registers your memory with your editor's AI - GitHub Copilot, Cursor, or Windsurf - at `memory.agentage.io/mcp`. Ask in chat, and the agent reads and answers from the same memory every AI you use shares. No command to run, no copy-paste, no local export.

## Features

- **Auto-installed** - on setup the Agentage Memory server registers itself with your editor's AI (VS Code's MCP provider; Cursor / Windsurf config) and appears in the MCP servers list - no command to run.
- **Works where you work** - VS Code (Copilot Agent mode), Cursor, and Windsurf.
- **Your editor handles sign-in** - OAuth 2.1 runs in the host's own MCP flow on first use. The extension stores no tokens and sends no data of its own.
- **One-time switch-on** - the first time its agent uses the server, VS Code shows a trust prompt + browser sign-in (it does not auto-start authenticated servers, by design); after that it stays on.

## Requirements

- An Agentage Memory account. Your editor prompts you to sign in the first time its AI uses the server.
- An MCP-capable AI in your editor: GitHub Copilot (Agent mode) in VS Code, Cursor, or Windsurf Cascade.

## Getting started

1. Install the extension. The **Agentage Memory** server appears automatically in your editor's MCP servers list.
2. Open your AI chat in agent mode; on first use, approve the trust prompt and sign in.
3. Ask something from your memory.

Didn't appear (older editor / unknown fork)? Run **`Agentage: Connect Memory to this editor`** from the Command Palette to register it manually.

## How it works

On activation the extension registers `memory.agentage.io/mcp` (Streamable HTTP) with your editor: VS Code via the **MCP provider API** (stable since 1.99, so the server appears on startup), Cursor and Windsurf by writing their MCP config file (merged, never overwritten). Your editor's agent runs OAuth 2.1 itself on first use. This extension stores no tokens and sends no data of its own. The `Agentage: Connect Memory to this editor` command does the same registration on demand.

## Settings

| Setting | Default | Description |
| --- | --- | --- |
| `agentage.mcpUrl` | `https://memory.agentage.io/mcp` | The MCP endpoint to register. Point at a different stack here. |

## Commands

| Command | What it does |
| --- | --- |
| `Agentage: Connect Memory to this editor` | Registers the MCP server so your editor's AI can read your memory. |

## Compatibility

VS Code (Copilot Agent mode), and via [Open VSX](https://open-vsx.org/extension/agentage/agentage): **Cursor, Windsurf, VSCodium**.

Auto-install needs VS Code **1.99+** (our minimum; the MCP provider API is stable from 1.99, authenticated MCP smoothest on 1.101+). Cursor and Windsurf are version-independent (the extension writes their MCP config file).

## Privacy

The extension only writes the server URL into your editor's MCP config (or opens the install deeplink). It stores no tokens, collects no telemetry, and sends no data of its own. Sign-in and all memory access happen through your editor's own MCP client.

## License

[MIT](./LICENSE)
49 changes: 49 additions & 0 deletions esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const esbuild = require('esbuild');

const production = process.argv.includes('--production');
const watch = process.argv.includes('--watch');

/** Surfaces build errors in the VS Code Problems panel during watch (F5 loop). */
const problemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => console.log('[watch] build started'));
build.onEnd((result) => {
for (const { text, location } of result.errors) {
console.error(`✘ [ERROR] ${text}`);
if (location) {
console.error(` ${location.file}:${location.line}:${location.column}:`);
}
}
console.log('[watch] build finished');
});
},
};

async function main() {
const ctx = await esbuild.context({
entryPoints: ['src/extension.ts'],
bundle: true,
format: 'cjs',
platform: 'node',
target: 'node18',
outfile: 'dist/extension.js',
external: ['vscode'],
minify: production,
sourcemap: !production,
sourcesContent: false,
logLevel: 'info',
plugins: [problemMatcherPlugin],
});
if (watch) {
await ctx.watch();
} else {
await ctx.rebuild();
await ctx.dispose();
}
}

main().catch((e) => {
console.error(e);
process.exit(1);
});
Binary file added media/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions media/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading