First shot
This commit is contained in:
parent
6ad505a422
commit
9b8f36aeed
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
build
|
1089
package-lock.json
generated
Normal file
1089
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "mtm-news-mcp",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"license": "ISC",
|
||||
"author": "",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
"mcp": "./build/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "node_modules/typescript/bin/tsc && chmod 755 build/index.js"
|
||||
},
|
||||
"files": ["build"],
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.13.0",
|
||||
"zod": "^3.25.67"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.3",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
10
run.sh
Executable file
10
run.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname "${0}")
|
||||
|
||||
if [ ! -f build/index.js ]; then
|
||||
npm i
|
||||
npm run build
|
||||
fi
|
||||
|
||||
node build/index.js
|
163
src/index.ts
Normal file
163
src/index.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
||||
// import { z } from "zod"
|
||||
|
||||
// Need move source outside of the project for custom settings
|
||||
const sources = [
|
||||
{
|
||||
name: '20 Minutes',
|
||||
items: [
|
||||
{
|
||||
keys: ['swiss-french'],
|
||||
name: 'Suisse romande',
|
||||
url: 'https://www.20min.ch/fr/suisse-romande',
|
||||
},
|
||||
{
|
||||
keys: ['swiss'],
|
||||
name: 'Suisse',
|
||||
url: 'https://www.20min.ch/fr/suisse',
|
||||
},
|
||||
{
|
||||
keys: ['international'],
|
||||
name: 'International',
|
||||
url: 'https://www.20min.ch/fr/monde',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '24 Heures',
|
||||
items: [
|
||||
{
|
||||
keys: ['swiss-french'],
|
||||
name: 'Suisse romande',
|
||||
url: 'https://www.24heures.ch/suisse-romande',
|
||||
},
|
||||
{
|
||||
keys: ['swiss'],
|
||||
name: 'Suisse',
|
||||
url: 'https://www.24heures.ch/suisse',
|
||||
},
|
||||
{
|
||||
keys: ['international'],
|
||||
name: 'International',
|
||||
url: 'https://www.24heures.ch/monde',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Blick',
|
||||
items: [
|
||||
{
|
||||
keys: ['suisse'],
|
||||
name: 'Suisse',
|
||||
url: 'https://www.blick.ch/fr/suisse/',
|
||||
},
|
||||
{
|
||||
keys: ['international'],
|
||||
name: 'International',
|
||||
url: 'https://www.blick.ch/fr/monde/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Le Temps',
|
||||
items: [
|
||||
{
|
||||
keys: ['swiss'],
|
||||
name: 'Suisse',
|
||||
url: 'https://www.letemps.ch/suisse',
|
||||
},
|
||||
{
|
||||
keys: ['international'],
|
||||
name: 'International',
|
||||
url: 'https://www.letemps.ch/monde',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Watson',
|
||||
items: [
|
||||
{
|
||||
keys: ['swiss'],
|
||||
name: 'Suisse',
|
||||
url: 'https://www.watson.ch/fr/suisse/',
|
||||
},
|
||||
{
|
||||
keys: ['international'],
|
||||
name: 'International',
|
||||
url: 'https://www.watson.ch/fr/international/',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
const layouts = [
|
||||
{
|
||||
name: 'switzerland',
|
||||
use: ['swiss-french', 'swiss'],
|
||||
},
|
||||
{
|
||||
name: 'international',
|
||||
use: ['international'],
|
||||
},
|
||||
]
|
||||
|
||||
const categories = {}
|
||||
const buildCategory = (use: Array<string>) => {
|
||||
const result: Array<{ name: string, url: string }> = []
|
||||
sources.forEach((source) => {
|
||||
source.items.forEach((item) => {
|
||||
use.forEach((key) => {
|
||||
item.keys.forEach((itemKey) => {
|
||||
let processed = false
|
||||
if(processed == false && key === itemKey) {
|
||||
result.push({
|
||||
name: source.name + ' - ' + item.name,
|
||||
url: item.url,
|
||||
})
|
||||
processed = true
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
layouts.forEach((layout) => {
|
||||
categories[layout.name] = buildCategory(layout.use)
|
||||
})
|
||||
|
||||
const server = new McpServer({
|
||||
name: "mtm-news-mcp",
|
||||
version: "1.0.0",
|
||||
capabilities: {
|
||||
resources: {},
|
||||
tools: {},
|
||||
},
|
||||
})
|
||||
|
||||
server.tool(
|
||||
"get-news",
|
||||
"Get latest news title and link ",
|
||||
{},
|
||||
() => {
|
||||
// Process
|
||||
//
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "",
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport()
|
||||
await server.connect(transport)
|
||||
console.error("MTM News MCP Server running on stdio")
|
||||
}
|
||||
main().catch((error) => {
|
||||
console.error("Fatal error in main():", error)
|
||||
process.exit(1)
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user