t212-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ T212_ENV=demo
2
+ T212_DEMO_API_KEY=
3
+ T212_DEMO_API_SECRET=
4
+ T212_LIVE_API_KEY=
5
+ T212_LIVE_API_SECRET=
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ - package-ecosystem: github-actions
8
+ directory: /
9
+ schedule:
10
+ interval: weekly
@@ -0,0 +1,40 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
15
+ with:
16
+ persist-credentials: false
17
+ - uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
18
+ - name: Check the release tag matches the package version
19
+ env:
20
+ TAG: ${{ github.event.release.tag_name }}
21
+ run: test "${TAG#v}" = "$(uv version --short)"
22
+ - run: uv run --locked pytest -q
23
+ - run: uv build
24
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ publish:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment: pypi
33
+ permissions:
34
+ id-token: write
35
+ steps:
36
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
37
+ with:
38
+ name: dist
39
+ path: dist/
40
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,26 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, macos-latest, windows-latest]
17
+ python: ["3.11", "3.13"]
18
+ runs-on: ${{ matrix.os }}
19
+ steps:
20
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21
+ with:
22
+ persist-credentials: false
23
+ - uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
24
+ with:
25
+ enable-cache: true
26
+ - run: uv run --python ${{ matrix.python }} --locked pytest -q
@@ -0,0 +1,13 @@
1
+ .env
2
+ .env.*
3
+ !.env.example
4
+ .venv/
5
+ __pycache__/
6
+ *.pyc
7
+ .pytest_cache/
8
+ dist/
9
+ *.egg-info/
10
+ logs/
11
+ .claude/settings.local.json
12
+ spec/
13
+ docs/research/
@@ -0,0 +1 @@
1
+ 355b9994677aa81fc248b13fa842e42c3e05c19f:.env.example:generic-api-key:4
t212_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adam Watson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.5
2
+ Name: t212-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the Trading 212 public API
5
+ Project-URL: Homepage, https://github.com/watsonam/t212-mcp
6
+ Project-URL: Issues, https://github.com/watsonam/t212-mcp/issues
7
+ Project-URL: Security, https://github.com/watsonam/t212-mcp/blob/main/SECURITY.md
8
+ Author: Adam Watson
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: isa,mcp,model-context-protocol,stocks,trading212
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: keyring>=25
23
+ Requires-Dist: mcp>=2.3
24
+ Requires-Dist: pydantic>=2.12
25
+ Description-Content-Type: text/markdown
26
+
27
+ # t212-mcp
28
+
29
+ I built this so I could ask an AI assistant about my Trading 212 Stocks ISA: what I hold, what it's worth, what orders I have open and what I've traded before. It also lets the assistant set up an order for me, but nothing is ever placed until I say yes to it myself.
30
+
31
+ It's an MCP server. MCP (Model Context Protocol) is the standard way to give an AI app new tools, so this works with Claude Code, Claude Desktop, GitHub Copilot in VS Code, Cursor and other apps that support MCP.
32
+
33
+ ## Please read this first
34
+
35
+ - This is a personal project. It isn't made by, affiliated with or endorsed by Trading 212.
36
+ - It can place real trades with real money. It comes with no warranty (see [LICENSE](https://github.com/watsonam/t212-mcp/blob/main/LICENSE)), and you're responsible for every order it places.
37
+ - Start with a read-only API key. Only add trading permission once you're comfortable with how it works.
38
+ - The only official copies are this repository, [github.com/watsonam/t212-mcp](https://github.com/watsonam/t212-mcp), and the [`t212-mcp` package on PyPI](https://pypi.org/project/t212-mcp/), which is built and published from this repository by GitHub Actions. Anything else with a similar name isn't mine, and could be built to steal your key.
39
+ - Found a security problem? Please report it privately, as described in [SECURITY.md](https://github.com/watsonam/t212-mcp/blob/main/SECURITY.md).
40
+
41
+ ## Where things stand
42
+
43
+ - I've connected it to my own live account and fetched my account summary. The other read tools are tested against fake responses, not my real account.
44
+ - The order tools are tested against fake responses only. They haven't placed a real order yet.
45
+ - When I asked Claude to place a trade, it declined. Claude may simply refuse to trade on your behalf, so with Claude you might only get as far as a preview. Other apps and models may go further, but every order still needs your yes.
46
+ - It runs on macOS, Linux and Windows, with Python 3.11 or newer. The tests run on all three every time something is pushed to `main` or a pull request is opened.
47
+
48
+ ## How ordering works
49
+
50
+ Placing an order always takes two steps.
51
+
52
+ 1. The assistant asks for a preview. You get back what the order is: the share, buy or sell, how many, and roughly what it'll cost in pounds.
53
+ 2. The assistant asks to confirm. The server then asks you directly, in a pop-up from your AI app, whether to place it. The question spells out the order exactly as it will be sent. If you say no, or close the question, nothing is sent.
54
+
55
+ The question comes from the server itself, so the assistant can't answer it for you. That only holds if your app shows you the question. An app set to accept these questions automatically, or one that lets the model answer them, removes that protection. If your app can't show the question at all, the order is refused. Cancelling an order asks you the same way, and tells you which order it is, for example "Cancel order 42: SELL 3 x Vanguard S&P 500 (VUSAl_EQ), stop order, stop 8500?".
56
+
57
+ A preview lasts 5 minutes and can only be used once.
58
+
59
+ The server checks these rules on every order, whatever the assistant asks for:
60
+
61
+ - Live trading is off unless you turn it on with `T212_LIVE_TRADING=1`. On the demo account (pretend money) it's always on.
62
+ - It only trades on accounts held in pounds (GBP).
63
+ - Each order is capped at £1,000 and each day at £2,000. Both caps count sells as well as buys. You can change them (see below).
64
+ - Trading 212 doesn't offer a live price feed, so the server only allows orders whose cost it can work out:
65
+ - A market order is only allowed for something you already own. It's priced from your holding, plus 5% in case the price moves.
66
+ - A limit or stop-limit order is priced at the limit you set.
67
+ - A stop buy is refused, because there's no way to know what it'll cost. Use a stop-limit order instead.
68
+ - For shares priced in another currency, such as US dollars, it works out the exchange rate from your largest holding in that currency. If you hold nothing in that currency, the order is refused.
69
+ - Holdings worth under £1 aren't used for pricing, because their rounded values aren't accurate enough.
70
+ - London shares are often priced in pence, so a limit price for them is in pence too.
71
+ - You can't sell more shares than you have available.
72
+ - An order is never sent twice. If Trading 212 doesn't give a clear answer, the server says the outcome is unknown, counts it towards your daily cap, and tells the assistant to check your open orders and history before trying again. Cancellations work the same way.
73
+ - Every preview, order and cancellation is written to a log on your computer, at `~/.local/state/t212-mcp/orders-<env>.jsonl`. Only your user account can read it. Here `~` means your home folder (on Windows, `C:\Users\you`). The daily cap is worked out from this log, per calendar day, and the log is locked while it's checked, so two chats can't both slip under the cap at the same time.
74
+
75
+ ## Setting it up
76
+
77
+ You'll need [uv](https://docs.astral.sh/uv/), a tool for running Python projects. There are two ways to get the server.
78
+
79
+ The quickest is from PyPI. uv downloads it the first time your AI app starts it, so there's nothing to install now. In the app snippets below, use `uvx` as the command and `["t212-mcp@0.1.0"]` as the arguments. Naming the version means you only move to a new one when you choose to.
80
+
81
+ The other way is to clone this repository and, from inside it, run:
82
+
83
+ ```bash
84
+ uv sync
85
+ ```
86
+
87
+ A clone uses exactly the dependency versions the tests ran with, and you can read every change before you `git pull` it.
88
+
89
+ Next, create an API key in the Trading 212 app, under Settings, then API. You'll get a key and a secret.
90
+
91
+ - To only read your account, tick account, portfolio, metadata, orders:read and history:orders.
92
+ - To place orders too, also tick orders:execute.
93
+ - If the app lets you, restrict the key to your home IP address.
94
+ - The demo account and your real account need separate keys.
95
+
96
+ The safest place for the key and secret is your computer's keychain (the macOS Keychain, Windows Credential Manager, or the Secret Service on Linux). Run these and paste each value when asked. Nothing shows on screen while you paste, which is normal.
97
+
98
+ ```bash
99
+ uv run keyring set t212-mcp live_api_key
100
+ uv run keyring set t212-mcp live_api_secret
101
+ ```
102
+
103
+ For a demo key, use `demo_api_key` and `demo_api_secret` instead. You can also set them as environment variables (see the settings table below), but never put them in a file you commit.
104
+
105
+ ## Connecting it to your AI app
106
+
107
+ The examples below use a clone. In each one, replace `/path/to/t212-mcp` with wherever you cloned this repository. The `--locked` flag makes uv use exactly the versions this repository was tested with, and `--no-dev` leaves out the test tools. On Windows, write the path with forward slashes, like `C:/Users/you/t212-mcp`, or double each backslash.
108
+
109
+ `T212_ENV=live` points it at your real account. Leave it out to use the demo account.
110
+
111
+ ### Claude Code
112
+
113
+ ```bash
114
+ claude mcp add trading212 -s user --env T212_ENV=live -- uv --directory /path/to/t212-mcp run --locked --no-dev t212-mcp
115
+ ```
116
+
117
+ Or, from PyPI:
118
+
119
+ ```bash
120
+ claude mcp add trading212 -s user --env T212_ENV=live -- uvx t212-mcp@0.1.0
121
+ ```
122
+
123
+ To allow live orders, add `--env T212_LIVE_TRADING=1`.
124
+
125
+ ### Claude Desktop
126
+
127
+ Add this to `claude_desktop_config.json`. On a Mac it's in `~/Library/Application Support/Claude/`, and on Windows it's in `%APPDATA%\Claude\`.
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "trading212": {
133
+ "command": "uv",
134
+ "args": ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"],
135
+ "env": {"T212_ENV": "live"}
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ Claude Desktop doesn't see your terminal's environment variables, so keep your key in the keychain, or put the variables in `env`.
142
+
143
+ ### GitHub Copilot in VS Code
144
+
145
+ Add this to `.vscode/mcp.json` in your workspace:
146
+
147
+ ```json
148
+ {
149
+ "servers": {
150
+ "trading212": {
151
+ "type": "stdio",
152
+ "command": "uv",
153
+ "args": ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"],
154
+ "env": {"T212_ENV": "live"}
155
+ }
156
+ }
157
+ }
158
+ ```
159
+
160
+ ### Cursor and Gemini CLI
161
+
162
+ Cursor (`~/.cursor/mcp.json`) and Gemini CLI (`~/.gemini/settings.json`) use the same `mcpServers` block as Claude Desktop.
163
+
164
+ ### OpenAI Codex CLI
165
+
166
+ Add this to `~/.codex/config.toml`:
167
+
168
+ ```toml
169
+ [mcp_servers.trading212]
170
+ command = "uv"
171
+ args = ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"]
172
+ env = { T212_ENV = "live" }
173
+ ```
174
+
175
+ ### Other apps
176
+
177
+ Any app that can run a local MCP server should work. For orders, the app also has to support "elicitation", which is how the server asks you to approve. If it doesn't, orders are refused but reading your account still works. These apps change where they keep their settings from time to time, so if a snippet doesn't work, check the app's own documentation.
178
+
179
+ ## Changing the limits
180
+
181
+ Create `~/.config/t212-mcp/config.toml` with your own caps, in pounds:
182
+
183
+ ```toml
184
+ max_order_gbp = 1000
185
+ max_daily_gbp = 2000
186
+ ```
187
+
188
+ The server won't start if the file has a typo, a setting it doesn't recognise, or a cap that isn't a positive number. That way a mistake can't quietly switch a cap off.
189
+
190
+ ## Settings
191
+
192
+ | Variable | What it does |
193
+ | --- | --- |
194
+ | `T212_ENV` | `demo` (the default) or `live` |
195
+ | `T212_LIVE_TRADING` | Set to `1` to allow orders on your live account |
196
+ | `T212_DEMO_API_KEY`, `T212_DEMO_API_SECRET` | Demo key, if you're not using the keychain |
197
+ | `T212_LIVE_API_KEY`, `T212_LIVE_API_SECRET` | Live key, if you're not using the keychain |
198
+ | `T212_CONFIG` | Where the caps file is (default `~/.config/t212-mcp/config.toml`) |
199
+ | `T212_CACHE_DIR` | Where the instrument list is cached |
200
+ | `T212_ORDER_LOG` | Where the order log is written |
201
+
202
+ ## Tools
203
+
204
+ These are the tools your AI app can use, with the Trading 212 permission each one needs.
205
+
206
+ | Tool | What it does | Permission |
207
+ | --- | --- | --- |
208
+ | `get_account_summary` | Cash, investments and total value | account |
209
+ | `get_positions` | What you hold and what it's worth | portfolio |
210
+ | `get_pending_orders` | Orders that haven't filled yet | orders:read |
211
+ | `get_order` | One open order | orders:read |
212
+ | `get_order_history` | Past orders, newest first | history:orders |
213
+ | `search_instruments` | Find a share's ticker by name, ticker or ISIN | metadata |
214
+ | `preview_market_order` | Preview a market order | portfolio, metadata |
215
+ | `preview_limit_order` | Preview a limit order | portfolio, metadata |
216
+ | `preview_stop_order` | Preview a stop order (sells only) | portfolio, metadata |
217
+ | `preview_stop_limit_order` | Preview a stop-limit order | portfolio, metadata |
218
+ | `confirm_order` | Ask you to approve a preview, then place it | orders:execute |
219
+ | `cancel_order` | Ask you to approve, then cancel an open order | orders:execute |
220
+
221
+ A few details:
222
+
223
+ - `get_positions` adds `priceInAccountCurrency`, the price of one share in pounds. Trading 212's own `currentPrice` is in the share's currency, which is often pence for London shares.
224
+ - The full list of shares is saved for 24 hours in `~/.cache/t212-mcp/`, because Trading 212 only allows it to be fetched about once a minute.
225
+ - The server spaces out its requests to stay inside Trading 212's rate limits.
226
+
227
+ ## Running the tests
228
+
229
+ ```bash
230
+ uv run pytest
231
+ ```
232
+
233
+ The tests use fake responses, so they never touch a real account. The code follows Trading 212's API specification, which isn't included here. To download it for reference on a Mac or Linux:
234
+
235
+ ```bash
236
+ mkdir -p spec && curl -sfL https://docs.trading212.com/_spec/api.json -o spec/api.json
237
+ ```
238
+
239
+ On Windows, in PowerShell:
240
+
241
+ ```powershell
242
+ New-Item -ItemType Directory -Force spec; Invoke-WebRequest https://docs.trading212.com/_spec/api.json -OutFile spec/api.json
243
+ ```
@@ -0,0 +1,217 @@
1
+ # t212-mcp
2
+
3
+ I built this so I could ask an AI assistant about my Trading 212 Stocks ISA: what I hold, what it's worth, what orders I have open and what I've traded before. It also lets the assistant set up an order for me, but nothing is ever placed until I say yes to it myself.
4
+
5
+ It's an MCP server. MCP (Model Context Protocol) is the standard way to give an AI app new tools, so this works with Claude Code, Claude Desktop, GitHub Copilot in VS Code, Cursor and other apps that support MCP.
6
+
7
+ ## Please read this first
8
+
9
+ - This is a personal project. It isn't made by, affiliated with or endorsed by Trading 212.
10
+ - It can place real trades with real money. It comes with no warranty (see [LICENSE](https://github.com/watsonam/t212-mcp/blob/main/LICENSE)), and you're responsible for every order it places.
11
+ - Start with a read-only API key. Only add trading permission once you're comfortable with how it works.
12
+ - The only official copies are this repository, [github.com/watsonam/t212-mcp](https://github.com/watsonam/t212-mcp), and the [`t212-mcp` package on PyPI](https://pypi.org/project/t212-mcp/), which is built and published from this repository by GitHub Actions. Anything else with a similar name isn't mine, and could be built to steal your key.
13
+ - Found a security problem? Please report it privately, as described in [SECURITY.md](https://github.com/watsonam/t212-mcp/blob/main/SECURITY.md).
14
+
15
+ ## Where things stand
16
+
17
+ - I've connected it to my own live account and fetched my account summary. The other read tools are tested against fake responses, not my real account.
18
+ - The order tools are tested against fake responses only. They haven't placed a real order yet.
19
+ - When I asked Claude to place a trade, it declined. Claude may simply refuse to trade on your behalf, so with Claude you might only get as far as a preview. Other apps and models may go further, but every order still needs your yes.
20
+ - It runs on macOS, Linux and Windows, with Python 3.11 or newer. The tests run on all three every time something is pushed to `main` or a pull request is opened.
21
+
22
+ ## How ordering works
23
+
24
+ Placing an order always takes two steps.
25
+
26
+ 1. The assistant asks for a preview. You get back what the order is: the share, buy or sell, how many, and roughly what it'll cost in pounds.
27
+ 2. The assistant asks to confirm. The server then asks you directly, in a pop-up from your AI app, whether to place it. The question spells out the order exactly as it will be sent. If you say no, or close the question, nothing is sent.
28
+
29
+ The question comes from the server itself, so the assistant can't answer it for you. That only holds if your app shows you the question. An app set to accept these questions automatically, or one that lets the model answer them, removes that protection. If your app can't show the question at all, the order is refused. Cancelling an order asks you the same way, and tells you which order it is, for example "Cancel order 42: SELL 3 x Vanguard S&P 500 (VUSAl_EQ), stop order, stop 8500?".
30
+
31
+ A preview lasts 5 minutes and can only be used once.
32
+
33
+ The server checks these rules on every order, whatever the assistant asks for:
34
+
35
+ - Live trading is off unless you turn it on with `T212_LIVE_TRADING=1`. On the demo account (pretend money) it's always on.
36
+ - It only trades on accounts held in pounds (GBP).
37
+ - Each order is capped at £1,000 and each day at £2,000. Both caps count sells as well as buys. You can change them (see below).
38
+ - Trading 212 doesn't offer a live price feed, so the server only allows orders whose cost it can work out:
39
+ - A market order is only allowed for something you already own. It's priced from your holding, plus 5% in case the price moves.
40
+ - A limit or stop-limit order is priced at the limit you set.
41
+ - A stop buy is refused, because there's no way to know what it'll cost. Use a stop-limit order instead.
42
+ - For shares priced in another currency, such as US dollars, it works out the exchange rate from your largest holding in that currency. If you hold nothing in that currency, the order is refused.
43
+ - Holdings worth under £1 aren't used for pricing, because their rounded values aren't accurate enough.
44
+ - London shares are often priced in pence, so a limit price for them is in pence too.
45
+ - You can't sell more shares than you have available.
46
+ - An order is never sent twice. If Trading 212 doesn't give a clear answer, the server says the outcome is unknown, counts it towards your daily cap, and tells the assistant to check your open orders and history before trying again. Cancellations work the same way.
47
+ - Every preview, order and cancellation is written to a log on your computer, at `~/.local/state/t212-mcp/orders-<env>.jsonl`. Only your user account can read it. Here `~` means your home folder (on Windows, `C:\Users\you`). The daily cap is worked out from this log, per calendar day, and the log is locked while it's checked, so two chats can't both slip under the cap at the same time.
48
+
49
+ ## Setting it up
50
+
51
+ You'll need [uv](https://docs.astral.sh/uv/), a tool for running Python projects. There are two ways to get the server.
52
+
53
+ The quickest is from PyPI. uv downloads it the first time your AI app starts it, so there's nothing to install now. In the app snippets below, use `uvx` as the command and `["t212-mcp@0.1.0"]` as the arguments. Naming the version means you only move to a new one when you choose to.
54
+
55
+ The other way is to clone this repository and, from inside it, run:
56
+
57
+ ```bash
58
+ uv sync
59
+ ```
60
+
61
+ A clone uses exactly the dependency versions the tests ran with, and you can read every change before you `git pull` it.
62
+
63
+ Next, create an API key in the Trading 212 app, under Settings, then API. You'll get a key and a secret.
64
+
65
+ - To only read your account, tick account, portfolio, metadata, orders:read and history:orders.
66
+ - To place orders too, also tick orders:execute.
67
+ - If the app lets you, restrict the key to your home IP address.
68
+ - The demo account and your real account need separate keys.
69
+
70
+ The safest place for the key and secret is your computer's keychain (the macOS Keychain, Windows Credential Manager, or the Secret Service on Linux). Run these and paste each value when asked. Nothing shows on screen while you paste, which is normal.
71
+
72
+ ```bash
73
+ uv run keyring set t212-mcp live_api_key
74
+ uv run keyring set t212-mcp live_api_secret
75
+ ```
76
+
77
+ For a demo key, use `demo_api_key` and `demo_api_secret` instead. You can also set them as environment variables (see the settings table below), but never put them in a file you commit.
78
+
79
+ ## Connecting it to your AI app
80
+
81
+ The examples below use a clone. In each one, replace `/path/to/t212-mcp` with wherever you cloned this repository. The `--locked` flag makes uv use exactly the versions this repository was tested with, and `--no-dev` leaves out the test tools. On Windows, write the path with forward slashes, like `C:/Users/you/t212-mcp`, or double each backslash.
82
+
83
+ `T212_ENV=live` points it at your real account. Leave it out to use the demo account.
84
+
85
+ ### Claude Code
86
+
87
+ ```bash
88
+ claude mcp add trading212 -s user --env T212_ENV=live -- uv --directory /path/to/t212-mcp run --locked --no-dev t212-mcp
89
+ ```
90
+
91
+ Or, from PyPI:
92
+
93
+ ```bash
94
+ claude mcp add trading212 -s user --env T212_ENV=live -- uvx t212-mcp@0.1.0
95
+ ```
96
+
97
+ To allow live orders, add `--env T212_LIVE_TRADING=1`.
98
+
99
+ ### Claude Desktop
100
+
101
+ Add this to `claude_desktop_config.json`. On a Mac it's in `~/Library/Application Support/Claude/`, and on Windows it's in `%APPDATA%\Claude\`.
102
+
103
+ ```json
104
+ {
105
+ "mcpServers": {
106
+ "trading212": {
107
+ "command": "uv",
108
+ "args": ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"],
109
+ "env": {"T212_ENV": "live"}
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ Claude Desktop doesn't see your terminal's environment variables, so keep your key in the keychain, or put the variables in `env`.
116
+
117
+ ### GitHub Copilot in VS Code
118
+
119
+ Add this to `.vscode/mcp.json` in your workspace:
120
+
121
+ ```json
122
+ {
123
+ "servers": {
124
+ "trading212": {
125
+ "type": "stdio",
126
+ "command": "uv",
127
+ "args": ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"],
128
+ "env": {"T212_ENV": "live"}
129
+ }
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### Cursor and Gemini CLI
135
+
136
+ Cursor (`~/.cursor/mcp.json`) and Gemini CLI (`~/.gemini/settings.json`) use the same `mcpServers` block as Claude Desktop.
137
+
138
+ ### OpenAI Codex CLI
139
+
140
+ Add this to `~/.codex/config.toml`:
141
+
142
+ ```toml
143
+ [mcp_servers.trading212]
144
+ command = "uv"
145
+ args = ["--directory", "/path/to/t212-mcp", "run", "--locked", "--no-dev", "t212-mcp"]
146
+ env = { T212_ENV = "live" }
147
+ ```
148
+
149
+ ### Other apps
150
+
151
+ Any app that can run a local MCP server should work. For orders, the app also has to support "elicitation", which is how the server asks you to approve. If it doesn't, orders are refused but reading your account still works. These apps change where they keep their settings from time to time, so if a snippet doesn't work, check the app's own documentation.
152
+
153
+ ## Changing the limits
154
+
155
+ Create `~/.config/t212-mcp/config.toml` with your own caps, in pounds:
156
+
157
+ ```toml
158
+ max_order_gbp = 1000
159
+ max_daily_gbp = 2000
160
+ ```
161
+
162
+ The server won't start if the file has a typo, a setting it doesn't recognise, or a cap that isn't a positive number. That way a mistake can't quietly switch a cap off.
163
+
164
+ ## Settings
165
+
166
+ | Variable | What it does |
167
+ | --- | --- |
168
+ | `T212_ENV` | `demo` (the default) or `live` |
169
+ | `T212_LIVE_TRADING` | Set to `1` to allow orders on your live account |
170
+ | `T212_DEMO_API_KEY`, `T212_DEMO_API_SECRET` | Demo key, if you're not using the keychain |
171
+ | `T212_LIVE_API_KEY`, `T212_LIVE_API_SECRET` | Live key, if you're not using the keychain |
172
+ | `T212_CONFIG` | Where the caps file is (default `~/.config/t212-mcp/config.toml`) |
173
+ | `T212_CACHE_DIR` | Where the instrument list is cached |
174
+ | `T212_ORDER_LOG` | Where the order log is written |
175
+
176
+ ## Tools
177
+
178
+ These are the tools your AI app can use, with the Trading 212 permission each one needs.
179
+
180
+ | Tool | What it does | Permission |
181
+ | --- | --- | --- |
182
+ | `get_account_summary` | Cash, investments and total value | account |
183
+ | `get_positions` | What you hold and what it's worth | portfolio |
184
+ | `get_pending_orders` | Orders that haven't filled yet | orders:read |
185
+ | `get_order` | One open order | orders:read |
186
+ | `get_order_history` | Past orders, newest first | history:orders |
187
+ | `search_instruments` | Find a share's ticker by name, ticker or ISIN | metadata |
188
+ | `preview_market_order` | Preview a market order | portfolio, metadata |
189
+ | `preview_limit_order` | Preview a limit order | portfolio, metadata |
190
+ | `preview_stop_order` | Preview a stop order (sells only) | portfolio, metadata |
191
+ | `preview_stop_limit_order` | Preview a stop-limit order | portfolio, metadata |
192
+ | `confirm_order` | Ask you to approve a preview, then place it | orders:execute |
193
+ | `cancel_order` | Ask you to approve, then cancel an open order | orders:execute |
194
+
195
+ A few details:
196
+
197
+ - `get_positions` adds `priceInAccountCurrency`, the price of one share in pounds. Trading 212's own `currentPrice` is in the share's currency, which is often pence for London shares.
198
+ - The full list of shares is saved for 24 hours in `~/.cache/t212-mcp/`, because Trading 212 only allows it to be fetched about once a minute.
199
+ - The server spaces out its requests to stay inside Trading 212's rate limits.
200
+
201
+ ## Running the tests
202
+
203
+ ```bash
204
+ uv run pytest
205
+ ```
206
+
207
+ The tests use fake responses, so they never touch a real account. The code follows Trading 212's API specification, which isn't included here. To download it for reference on a Mac or Linux:
208
+
209
+ ```bash
210
+ mkdir -p spec && curl -sfL https://docs.trading212.com/_spec/api.json -o spec/api.json
211
+ ```
212
+
213
+ On Windows, in PowerShell:
214
+
215
+ ```powershell
216
+ New-Item -ItemType Directory -Force spec; Invoke-WebRequest https://docs.trading212.com/_spec/api.json -OutFile spec/api.json
217
+ ```
@@ -0,0 +1,24 @@
1
+ # Security
2
+
3
+ This server can read a brokerage account and place real orders, so I take security problems seriously.
4
+
5
+ ## Reporting a problem
6
+
7
+ Please don't open a public issue for a security problem. Use GitHub's private reporting instead: go to the Security tab of this repository and choose "Report a vulnerability". Only I can see what you send.
8
+
9
+ This is a personal project, so a reply may take a few days.
10
+
11
+ ## Which version
12
+
13
+ Only the latest release, and the latest code on `main`, are supported.
14
+
15
+ ## The official source
16
+
17
+ The only official sources are [github.com/watsonam/t212-mcp](https://github.com/watsonam/t212-mcp) and the [`t212-mcp` package on PyPI](https://pypi.org/project/t212-mcp/). The PyPI package is only ever built and published from this repository by GitHub Actions, never uploaded by hand. If you see a package or a copy with a similar name somewhere else, it isn't mine, and it could be built to steal your Trading 212 key.
18
+
19
+ ## If your API key may have leaked
20
+
21
+ 1. Open the Trading 212 app, go to Settings, then API, and delete the key straight away.
22
+ 2. Check your recent orders and account activity.
23
+ 3. Create a new key, with only the permissions you need, and restrict it to your IP address if the app lets you.
24
+ 4. Store the new key in your system keychain (see the README), not in a file.
@@ -0,0 +1,39 @@
1
+ [project]
2
+ name = "t212-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server for the Trading 212 public API"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ authors = [{ name = "Adam Watson" }]
9
+ keywords = ["mcp", "trading212", "model-context-protocol", "stocks", "isa"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Intended Audience :: End Users/Desktop",
13
+ "Operating System :: OS Independent",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Office/Business :: Financial :: Investment",
19
+ ]
20
+ dependencies = ["mcp>=2.3", "httpx>=0.27", "keyring>=25", "pydantic>=2.12"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/watsonam/t212-mcp"
24
+ Issues = "https://github.com/watsonam/t212-mcp/issues"
25
+ Security = "https://github.com/watsonam/t212-mcp/blob/main/SECURITY.md"
26
+
27
+ [project.scripts]
28
+ t212-mcp = "t212_mcp.server:main"
29
+
30
+ [dependency-groups]
31
+ dev = ["pytest>=8", "pytest-asyncio>=0.24", "respx>=0.21"]
32
+
33
+ [build-system]
34
+ requires = ["hatchling"]
35
+ build-backend = "hatchling.build"
36
+
37
+ [tool.pytest.ini_options]
38
+ asyncio_mode = "auto"
39
+ testpaths = ["tests"]
File without changes