https://mcp.newtimespace.com/mcp. Transport is Streamable HTTP. No API key is required.search_articles (search a list) and get_article_detail (fetch full text).{"page":1,"limit":10} and do not pass query.{"query":"Xiaomi"}. Pass one core keyword only — no spaces, no AND/OR.start_date / end_date (YYYY-MM-DD). A date parameter does not exist.ID from the list and call get_article_detail (max 10 IDs per call).⚠️ 服务端提示 (a server hint), adjust the parameters as advised and retry once. On an empty result, first drop the category / date filters.| Item | Value |
|---|---|
| Endpoint | https://mcp.newtimespace.com/mcp |
| Transport | Streamable HTTP (POST request, SSE response) |
| Authentication | None — no API key |
| Server Name | nts-news-mcp-server |
| Version | 2.1.0 |
| Protocol Version | Supports 2024-11-05 / 2025-03-26 / 2025-06-18 / 2025-11-25. The server echoes back whatever version the client requests; if it cannot recognise the value it falls back to the highest, 2025-11-25. Hand-written clients can simply send 2025-03-26. |
| Tools | search_articles, get_article_detail |
| CORS | Cross-origin allowed (Access-Control-Allow-Origin: *) — callable directly from a browser |
Sessions are reusable: the initialize response header returns mcp-session-id, which must be echoed on every following request. Standard MCP clients handle this automatically; hand-written HTTP clients should see Section 12.
First, work out which kind of agent you are
Case A — you can add an MCP server (Claude Desktop, Cursor, Cline, WorkBuddy, Cherry Studio, any MCP-capable IDE or desktop app)Standard clients (Claude Desktop / Cursor / Cline / WorkBuddy, etc.)
{
"mcpServers": {
"nts-news": {
"url": "https://mcp.newtimespace.com/mcp"
}
}
}
url on its own is the most compatible form. If your client requires an explicit transport type, add "type" as documented by that client — common values are http or streamable-http (naming differs between clients). If your config file uses a different top-level key (VS Code uses servers), adapt the structure accordingly; the url value stays the same. This service supports Streamable HTTP only — not the legacy two-endpoint HTTP+SSE mode.
Direct URL (clients that accept a remote URL)
https://mcp.newtimespace.com/mcp
| Tool | Purpose | Description |
|---|---|---|
search_articles |
Search list | Searches articles by keyword / category / date range and returns a Markdown list of summaries plus metadata. Bodies are not included by default. |
get_article_detail |
Full text | Fetches the complete body of one or more articles by article_id (Markdown, markup already stripped). Max 10 IDs per call. |
All parameters are optional. Sending none returns the newest articles site-wide.
| Parameter | Type | Default | Description and constraints |
|---|---|---|---|
query optional |
string | — | Core search term, matched against both title and summary. Pass a single subject word (e.g. Xiaomi, NVIDIA, 01810).Do not send space-separated words or boolean operators (e.g. Xiaomi earnings, Xiaomi AND earnings) — the server returns an empty result together with a warning.Stock codes work ( 01810, 03033.HK). |
category optional |
string | — | Category name, exact match, case-sensitive, and it must pair with language (a Chinese category will not work with en). Valid values in Section 6. Omit to search everything. |
language optional |
enum | zh-cn |
zh-cn Simplified Chinese | zh-hk Traditional Chinese | en English. Also determines the response language and the url path. |
start_date optional |
string | — | Start date, YYYY-MM-DD, inclusive from 00:00:00. Can be used alone (meaning “from that day to now”). |
end_date optional |
string | — | End date, YYYY-MM-DD, inclusive to 23:59:59. For a single day, pass the same date for both. |
sort optional |
enum | publish_time |
publish_time | id. |
order optional |
enum | desc |
desc | asc. |
include_content optional |
boolean | false |
Whether to attach the full body to each list item. Defaults to false (summary only) to save tokens. Use only when fetching 1–3 articles; for batch reading use get_article_detail instead. |
page optional |
integer | 1 |
Page number, minimum 1. Sending 0 is rejected with a validation error. |
limit optional |
integer | 10 |
Items per page, 1–100. Above 100 is rejected with a validation error. Watch the size: limit=100 returns roughly 40,000 characters (≈20,000 tokens) in a single response. Use 5–10 for normal work. |
Unknown parameter names never raise an error — they are silently dropped
If you send an undefined parameter (for example a date as "date": "2026-10-20"), the server does not complain. It ignores the field and returns the newest articles site-wide. Your agent believes the filter applied while the data is unrelated — this is the single most common pitfall.
Use the exact parameter names above. Date filtering exists only as start_date / end_date.
Category names change with the language, must match exactly, and are case-sensitive.
| language | Allowed categories |
|---|---|
zh-cn | 财经 | 新股 | ETF | 科技 | 出海 | 新时空研究院 | 财经FAQ |
zh-hk | 財經 | 新股 | ETF | 科技 | 出海 | 新時空研究院 | 財經FAQ |
en | Finance | IPO | ETF | Tech | Overseas | Research | 财经FAQ |
If you are unsure which categories exist
Send a placeholder category (e.g. {"category":"_"}). The server will not error; instead it returns the authoritative category list for that language inside a ⚠️ 服务端提示 hint. Re-fill category accordingly and retry.
| Parameter | Type | Required | Description |
|---|---|---|---|
article_ids |
string | Yes | Article IDs, comma-separated, e.g. "1455411" or "1455411,1455409".Max 10 per call; more returns a [PARAMETER_EXCEEDED_LIMIT] error. A space after the comma is tolerated. |
language |
enum | No | zh-cn (default) | zh-hk | en. The same article_id returns the body in the requested language — IDs are shared across languages. |
article_id comes from the (ID: 1455605) marker on each item in the search_articles list.
search_articles
The tool returns a single block of Markdown text, not JSON. The structure is always: a header line, a divider, then one block per article. Below is a real language:"en" response:
📋 NewTimeSpace 资讯检索结果 关键词: NVIDIA | 分类: 全部 | 语言: en 日期: * ~ * | 排序: publish_time desc 第 1/20 页 · 本页 2 条 · 总计 40 条 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 【1】HK Stock Connect Daily Report: 51WORLD Rises 30.31% as Its 51Sim Unit Joins the NVIDIA Halos SAFE Ecosystem - 20261023 (ID: 1455605) · 分类: Research | 语言: en | 发布时间: 2026-10-23T17:59:31+08:00 · 作者: 孙佳怡 | 来源: NewTimeSpace | 标签: NewTimeSpace,HK Stock Connect,HK Stock Connect ETF · 摘要: On October 23, 2026, the HSTECH rose 2.05% and the HSI added 0.69%. 51WORLD led Stock Connect gainers, up 30.31%, as southbound net selling hit HK$1.67 billion. · 链接: https://www.newtimespace.com/en/research/1455605.html ────────────────────────────── 【2】…
Field labels stay in Chinese even when language is en
Only article content switches language. The wrapper labels are always Chinese:📋 资讯检索结果, 关键词, 分类, 语言, 日期, 排序, 第 1/20 页, 本页 2 条, 总计 40 条, plus the per-item prefixes · 作者: · 来源: · 标签: · 摘要: · 链接:.摘要 (summary) may be truncated (ending with ......); fetch get_article_detail for the full text.发布时间 is ISO 8601 with a timezone offset (+08:00).链接 path follows language (/zh-cn/, /zh-hk/, /en/).include_content: true, each item becomes a 📰 文章详情 [ID: …] block that includes 正文内容 (N 字,Markdown).get_article_detail
📰 文章详情 [ID: 1455605] 标题: HK Stock Connect Daily Report: 51WORLD Rises 30.31% as Its 51Sim Unit Joins the NVIDIA Halos SAFE Ecosystem - 20261023 分类: Research | 语言: en | 时间: 2026-10-23T17:59:31+08:00 作者: 孙佳怡 | 来源: NewTimeSpace | 标签: NewTimeSpace,HK Stock Connect,HK Stock Connect ETF 链接: https://www.newtimespace.com/en/research/1455605.html ──────────────────────────────────────── 正文内容 (14137 字,Markdown): I. Market Overview On October 23, 2026, the three major Hong Kong indices opened higher and briefly turned negative before rebounding with the A-share market in the afternoon and closing higher…
Multiple articles are returned as consecutive 📰 文章详情 [ID: …] blocks. A single body typically runs 800–2,800 characters in Chinese; English reports can be considerably longer.
The standard two-step pattern: search the list to get IDs, then fetch bodies on demand. This avoids pulling large volumes of text into your context at once.
search_articles({"query":"Xiaomi","limit":10}). Check the total matches in the header line — tens of thousands means the keyword is too broad, zero means it is too narrow.IDs from the list.get_article_detail({"article_ids":"1455411,1455409"}).title + publish time + link in your output so the user can trace every claim.Common scenarios
| Scenario | How to call |
|---|---|
| Latest news today | {"page":1,"limit":10} — omit query |
| Recent coverage of a company | {"query":"Xiaomi","limit":10} |
| Company within one section | {"query":"Xiaomi","category":"Tech","language":"en"} |
| Specific date range | {"start_date":"2026-10-20","end_date":"2026-10-22","limit":10} |
| One section only | {"category":"ETF","limit":10} |
| English coverage | {"query":"NVIDIA","language":"en","category":"Tech"} |
| Deep dive on one article | Search for the ID first → get_article_detail({"article_ids":"1455605"}) |
| Full text of 1–3 articles only | {"query":"Xiaomi","limit":2,"include_content":true} |
The server distinguishes two kinds of failure: out-of-range parameters return a tool error (isError: true), while no matches returns an empty result plus a hint.
| Returned text | Meaning | What to do |
|---|---|---|
MCP error -32602: Input validation error: Number must be less than or equal to 100 at limit |
Parameter out of range | Set limit ≤100 and page ≥1, then retry. |
❌ 获取文章详情失败: API HTTP 400 [PARAMETER_EXCEEDED_LIMIT] … 单次最多支持查询 10 条 |
Too many IDs | Split article_ids into batches of ≤10. |
📭 未找到符合条件的新闻数据。。 |
No matches | Drop category and date filters, keep only query, retry. If still empty, use a shorter core keyword. |
📭 未找到匹配该分类的新闻数据。。 + ⚠️ 服务端提示:… 下可用分类:… |
Category not valid for this language | Re-fill category using the list returned in the hint. |
⚠️ 服务端提示:query 含空格或布尔运算符,建议仅传入单个核心关键词 |
Search term too complex | Retry with a single word, e.g. "Xiaomi AND earnings" → "Xiaomi". |
📭 未找到指定的文章内容 [IDs: 999999999] |
ID does not exist | Get valid IDs from search_articles; never invent them. |
Make use of the warnings
If the response ends with ⚠️ 服务端提示(请据此自我修正) (“server hint — self-correct accordingly”), the request succeeded but the parameters were problematic. Read the hint, fix the parameters and retry once — do not report the empty result to the user as “there is no such news”.
| Wrong | Right |
|---|---|
Filtering dates with a date parameter | Use start_date + end_date; date is silently ignored |
| Assuming the summary is enough and skipping full text | List summaries are truncated — long-form analysis must call get_article_detail |
| Parsing the returned text as JSON | It is Markdown text; read it directly or extract IDs with (ID: (\d+)) |
Sending "Xiaomi earnings Q3" as query | Send "Xiaomi", then narrow down by publish_time or by reading the bodies |
Pairing a Chinese category with en ({"category":"财经","language":"en"}) | Use Finance for English; category must pair with language |
limit=1000 to fetch everything at once | 100 is the maximum; paginate or narrow the date range |
Sending 20 IDs in one article_ids value | Max 10 per call; batch them |
Guessing parameter names (keyword, q, lang, type) | Undefined parameters are dropped silently — you will just get the newest articles site-wide |
If your environment cannot register an MCP server, you can still use this service as long as you can send a POST request. The flow takes two steps: initialize to obtain a session ID, then tools/call with that ID attached.
| Item | Requirement |
|---|---|
| Method | Must be POST. GET is rejected. |
| Path | https://mcp.newtimespace.com/mcp (a trailing / is tolerated) |
Content-Type | Must be application/json |
Accept | Must contain both values: application/json, text/event-stream. Sending only one returns 406. |
Mcp-Session-Id | Required on every request after initialize; take the value from the mcp-session-id response header. |
Both steps chained together, returning data directly:
SID=$(curl -si --max-time 40 -X POST https://mcp.newtimespace.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"web-agent","version":"1.0"}}}' \
| grep -i '^mcp-session-id:' | tr -d '\r' | cut -d' ' -f2) && \
curl -s --max-time 40 -X POST https://mcp.newtimespace.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_articles","arguments":{"query":"NVIDIA","language":"en","limit":2}}}'
This is simply the two steps in 12.3 joined with &&. If your runtime can only execute one command at a time, use this version.
Step one — handshake and capture the session ID:
SID=$(curl -si --max-time 40 -X POST https://mcp.newtimespace.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"web-agent","version":"1.0"}}}' \
| grep -i '^mcp-session-id:' | tr -d '\r' | cut -d' ' -f2)
echo "SID=$SID"
Important when running the steps separately
SID is a shell variable, not a literal in the command. Both steps must run in the same shell session, otherwise the second step gets an empty value and receives 400 Session missing or invalid.-H "Mcp-Session-Id: the-actual-value" — do not use $SID.
Step two — call the tool with the session ID:
curl -s --max-time 40 -X POST https://mcp.newtimespace.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_articles","arguments":{"query":"NVIDIA","language":"en","limit":3}}}'
The response is an SSE stream; the payload sits on the data: line:
event: message
data: {"result":{"content":[{"type":"text","text":"📋 NewTimeSpace 资讯检索结果n…"}],"isError":false},"jsonrpc":"2.0","id":2}
To extract: take the JSON after data: and read result.content[0].text — that is the Markdown text shown in Section 8. If result.isError is true, text holds an error message instead of data.
If Python is available and you can pip install mcp, the official SDK is the least effort — it handles the handshake and session for you:
import anyio
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
async def main():
async with streamable_http_client("https://mcp.newtimespace.com/mcp") as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print([t.name for t in tools.tools])
r = await session.call_tool(
"search_articles", {"query": "NVIDIA", "language": "en", "limit": 3}
)
print(r.content[0].text)
anyio.run(main)
Written for mcp 2.x: passing the URL alone is enough, and the SDK negotiates the protocol version up to 2025-11-25. Note that fields became snake_case in 2.x (is_error, input_schema) — older tutorials using isError will raise an AttributeError.
notifications/initialized is optional. The spec recommends it, but this server does not enforce it — calling tools/call straight after initialize works. Sending it returns an empty 202 response and causes no harm.MCP-Protocol-Version header is optional; an incorrect value does not break the call either.| Symptom | Actual cause | Fix |
|---|---|---|
406 Not Acceptable: Client must accept both application/json and text/event-stream |
The Accept header does not contain both values | Send Accept: application/json, text/event-stream |
400 Bad Request: Session missing or invalid |
Four possible causes: ① no prior initialize ② the request is missing Content-Type: application/json ③ the initialize body lacks protocolVersion or clientInfo ④ the session has expired |
Do not be misled by the wording into assuming it is only a session problem. Fix the headers and body first, then initialize again |
404 Cannot POST / |
Posted to the domain root | The path must include /mcp |
400 Invalid or missing session ID |
A GET was sent to the endpoint | GET scraping is not supported — use POST |
{"error":{"code":-32601,"message":"Method not found"}} |
Misspelled method |
Only initialize / tools/list / tools/call |
MCP error -32602: Tool xxx not found |
Misspelled tool name | Only search_articles and get_article_detail; run tools/list to verify |
Run a sanity check first
Send{"jsonrpc":"2.0","id":1,"method":"tools/list"} and confirm the response contains both search_articles and get_article_detail with their parameter schemas before making real calls. This surfaces problems before you start guessing at parameters rather than after an empty result.
Browser access
Access-Control-Allow-Origin: * is set and mcp-session-id is exposed via Access-Control-Expose-Headers, so browser JavaScript using fetch can read that response header and complete the whole handshake client-side.
| Item | Limit |
|---|---|
| Authentication | None — public access |
| Items per page | 1–100, default 10 |
| Detail batch | Max 10 article_id values per call |
| Response size | limit=10 ≈ 4,000 characters; limit=100 ≈ 40,000 characters (≈20,000 tokens) |
| Latency | Typically 0.2–1.5 s |
| Language coverage | zh-cn / zh-hk / en; the same article ID is available in all three |