@songyaeji/security-paper-mcp-server 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Security Paper Search MCP Server
2
+
3
+ 보안 학회 논문을 검색하는 MCP (Model Context Protocol) 서버입니다.
4
+
5
+ ## 지원 컨퍼런스
6
+
7
+ ### Top-Tier (4대 학회)
8
+ - **S&P** (IEEE Symposium on Security and Privacy)
9
+ - **USENIX Security** (USENIX Security Symposium)
10
+ - **CCS** (ACM Conference on Computer and Communications Security)
11
+ - **NDSS** (Network and Distributed System Security Symposium)
12
+
13
+ ### Second-Tier
14
+ - **ACSAC** (Annual Computer Security Applications Conference)
15
+ - **RAID** (Research in Attacks, Intrusions and Defenses)
16
+ - **ESORICS** (European Symposium on Research in Computer Security)
17
+
18
+ ## 설치
19
+
20
+ ```bash
21
+ npm install
22
+ npm run build
23
+ ```
24
+
25
+ ## Claude Code에서 사용하기
26
+
27
+ `~/.claude/claude_desktop_config.json` 또는 `settings.json`에 추가:
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "security-papers": {
33
+ "command": "node",
34
+ "args": ["<절대경로>/security-paper-mcp-server/dist/index.js"]
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## 제공 도구 (Tools)
41
+
42
+ ### 1. search_papers
43
+ 논문 검색 (키워드, 저자, 연도, 컨퍼런스 필터)
44
+
45
+ ```
46
+ search_papers(
47
+ keyword: "fuzzing", // 검색 키워드
48
+ author: "John Smith", // 저자명
49
+ yearFrom: 2022, // 시작 연도
50
+ yearTo: 2024, // 종료 연도
51
+ conferences: ["sp", "ccs"], // 특정 컨퍼런스
52
+ tier: "top", // top, second, all
53
+ limit: 50 // 최대 결과 수
54
+ )
55
+ ```
56
+
57
+ ### 2. get_conference_papers
58
+ 특정 컨퍼런스의 특정 연도 논문 조회
59
+
60
+ ```
61
+ get_conference_papers(
62
+ conference: "sp", // sp, usenix, ccs, ndss, acsac, raid, esorics
63
+ year: 2024
64
+ )
65
+ ```
66
+
67
+ ### 3. list_conferences
68
+ 지원되는 컨퍼런스 목록 확인
69
+
70
+ ```
71
+ list_conferences()
72
+ ```
73
+
74
+ ### 4. get_stats
75
+ 검색 결과 통계 (연도별, 컨퍼런스별)
76
+
77
+ ```
78
+ get_stats(
79
+ keyword: "malware",
80
+ tier: "top"
81
+ )
82
+ ```
83
+
84
+ ## 사용 예시
85
+
86
+ Claude에게 다음과 같이 요청하면 됩니다:
87
+
88
+ - "2024년 S&P 논문 중 fuzzing 관련 논문 찾아줘"
89
+ - "CCS와 NDSS에서 발표된 malware 분석 논문 검색해줘"
90
+ - "2022년부터 2024년까지 top-tier 학회의 LLM 보안 관련 논문 찾아줘"
91
+ - "USENIX Security 2023 논문 목록 보여줘"
92
+
93
+ ## 데이터 소스
94
+
95
+ 이 서버는 [DBLP](https://dblp.org) API를 사용하여 논문 정보를 검색합니다.
96
+
97
+ ## 개발
98
+
99
+ ```bash
100
+ # 개발 모드 실행
101
+ npm run dev
102
+
103
+ # 빌드
104
+ npm run build
105
+
106
+ # 실행
107
+ npm start
108
+ ```
109
+
110
+ ## 라이선스
111
+
112
+ MIT
@@ -0,0 +1,115 @@
1
+ {
2
+ "conferences": {
3
+ "top_tier": {
4
+ "sp": {
5
+ "name": "IEEE Symposium on Security and Privacy (S&P/Oakland)",
6
+ "shortName": "S&P",
7
+ "tier": "top",
8
+ "urls": {
9
+ "2020": "https://www.ieee-security.org/TC/SP2020/program-papers.html",
10
+ "2021": "https://www.ieee-security.org/TC/SP2021/program-papers.html",
11
+ "2022": "https://www.ieee-security.org/TC/SP2022/program-papers.html",
12
+ "2023": "https://www.ieee-security.org/TC/SP2023/program-papers.html",
13
+ "2024": "https://www.ieee-security.org/TC/SP2024/program-papers.html",
14
+ "2025": "https://www.ieee-security.org/TC/SP2025/program-papers.html"
15
+ },
16
+ "dblpKey": "conf/sp"
17
+ },
18
+ "usenix": {
19
+ "name": "USENIX Security Symposium",
20
+ "shortName": "USENIX Security",
21
+ "tier": "top",
22
+ "urls": {
23
+ "2020": "https://www.usenix.org/conference/usenixsecurity20/technical-sessions",
24
+ "2021": "https://www.usenix.org/conference/usenixsecurity21/technical-sessions",
25
+ "2022": "https://www.usenix.org/conference/usenixsecurity22/technical-sessions",
26
+ "2023": "https://www.usenix.org/conference/usenixsecurity23/technical-sessions",
27
+ "2024": "https://www.usenix.org/conference/usenixsecurity24/technical-sessions",
28
+ "2025": "https://www.usenix.org/conference/usenixsecurity25/technical-sessions"
29
+ },
30
+ "dblpKey": "conf/uss"
31
+ },
32
+ "ccs": {
33
+ "name": "ACM Conference on Computer and Communications Security (CCS)",
34
+ "shortName": "CCS",
35
+ "tier": "top",
36
+ "urls": {
37
+ "2020": "https://www.sigsac.org/ccs/CCS2020/accepted-papers.html",
38
+ "2021": "https://www.sigsac.org/ccs/CCS2021/accepted-papers.html",
39
+ "2022": "https://www.sigsac.org/ccs/CCS2022/program/accepted-papers.html",
40
+ "2023": "https://www.sigsac.org/ccs/CCS2023/tocs/tocs-ccs23.html",
41
+ "2024": "https://www.sigsac.org/ccs/CCS2024/program/accepted-papers.html",
42
+ "2025": "https://www.sigsac.org/ccs/CCS2025/accepted-papers/"
43
+ },
44
+ "dblpKey": "conf/ccs"
45
+ },
46
+ "ndss": {
47
+ "name": "Network and Distributed System Security Symposium (NDSS)",
48
+ "shortName": "NDSS",
49
+ "tier": "top",
50
+ "urls": {
51
+ "2020": "https://www.ndss-symposium.org/ndss2020/accepted-papers/",
52
+ "2021": "https://www.ndss-symposium.org/ndss2021/accepted-papers/",
53
+ "2022": "https://www.ndss-symposium.org/ndss2022/accepted-papers/",
54
+ "2023": "https://www.ndss-symposium.org/ndss2023/accepted-papers/",
55
+ "2024": "https://www.ndss-symposium.org/ndss2024/accepted-papers/",
56
+ "2025": "https://www.ndss-symposium.org/ndss2025/accepted-papers/"
57
+ },
58
+ "dblpKey": "conf/ndss"
59
+ }
60
+ },
61
+ "second_tier": {
62
+ "acsac": {
63
+ "name": "Annual Computer Security Applications Conference (ACSAC)",
64
+ "shortName": "ACSAC",
65
+ "tier": "second",
66
+ "urls": {
67
+ "2020": "https://www.acsac.org/2020/program/papers/",
68
+ "2021": "https://www.acsac.org/2021/program/papers/",
69
+ "2022": "https://www.acsac.org/2022/program/papers/",
70
+ "2023": "https://www.acsac.org/2023/program/papers/",
71
+ "2024": "https://www.acsac.org/2024/program/"
72
+ },
73
+ "dblpKey": "conf/acsac"
74
+ },
75
+ "raid": {
76
+ "name": "International Symposium on Research in Attacks, Intrusions and Defenses (RAID)",
77
+ "shortName": "RAID",
78
+ "tier": "second",
79
+ "urls": {
80
+ "2020": "https://raid2020.org/accepted-papers/",
81
+ "2021": "https://dl.acm.org/doi/proceedings/10.1145/3471621",
82
+ "2022": "https://dblp.org/db/conf/raid/raid2022.html",
83
+ "2023": "https://dblp.org/db/conf/raid/raid2023.html",
84
+ "2024": "https://raid2024.github.io/accepted_open.html"
85
+ },
86
+ "dblpKey": "conf/raid"
87
+ },
88
+ "esorics": {
89
+ "name": "European Symposium on Research in Computer Security (ESORICS)",
90
+ "shortName": "ESORICS",
91
+ "tier": "second",
92
+ "urls": {
93
+ "2020": "https://dblp.org/db/conf/esorics/esorics2020-1.html",
94
+ "2021": "https://esorics2021.athene-center.de/program.php",
95
+ "2022": "https://esorics2022.compute.dtu.dk/program.html",
96
+ "2023": "https://esorics2023.org/program/",
97
+ "2024": "https://dblp.org/db/conf/esorics/esorics2024-1.html"
98
+ },
99
+ "dblpKey": "conf/esorics"
100
+ }
101
+ }
102
+ },
103
+ "dblpBaseUrl": "https://dblp.org/search/publ/api",
104
+ "alternativeSources": {
105
+ "dblp": {
106
+ "description": "DBLP Computer Science Bibliography - comprehensive paper database",
107
+ "searchUrl": "https://dblp.org/search/publ/api?q={query}+venue:{venue}&format=json",
108
+ "venueUrl": "https://dblp.org/db/conf/{venue}/index.html"
109
+ },
110
+ "semanticScholar": {
111
+ "description": "Semantic Scholar API for paper metadata",
112
+ "searchUrl": "https://api.semanticscholar.org/graph/v1/paper/search"
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import * as z from 'zod';
5
+ import { searchPapers, searchByConference, listAvailableConferences, getAvailableYears, getConferenceInfo } from './paperSearch.js';
6
+ const server = new McpServer({
7
+ name: 'security-paper-search',
8
+ version: '1.0.0'
9
+ });
10
+ // Tool 1: Search papers with various filters
11
+ server.registerTool('search_papers', {
12
+ title: 'Search Security Papers',
13
+ description: `Search for security research papers from top-tier (S&P, USENIX Security, CCS, NDSS) and second-tier (ACSAC, RAID, ESORICS) conferences.
14
+
15
+ Supports filtering by:
16
+ - keyword: Search in paper titles
17
+ - author: Author name
18
+ - yearFrom/yearTo: Year range (2020-present)
19
+ - conferences: Specific conference keys (sp, usenix, ccs, ndss, acsac, raid, esorics)
20
+ - tier: "top", "second", or "all"`,
21
+ inputSchema: {
22
+ keyword: z.string().optional().describe('Keyword to search in paper titles'),
23
+ author: z.string().optional().describe('Author name to search'),
24
+ yearFrom: z.number().min(2020).max(2026).optional().describe('Start year (default: 2020)'),
25
+ yearTo: z.number().min(2020).max(2026).optional().describe('End year (default: current year)'),
26
+ conferences: z.array(z.string()).optional().describe('Conference keys: sp, usenix, ccs, ndss, acsac, raid, esorics'),
27
+ tier: z.enum(['top', 'second', 'all']).optional().describe('Conference tier filter'),
28
+ limit: z.number().min(1).max(200).optional().describe('Max results (default: 50)')
29
+ }
30
+ }, async (args) => {
31
+ try {
32
+ const papers = await searchPapers({
33
+ keyword: args.keyword,
34
+ author: args.author,
35
+ yearFrom: args.yearFrom || 2020,
36
+ yearTo: args.yearTo || new Date().getFullYear(),
37
+ conferences: args.conferences,
38
+ tier: args.tier || 'all',
39
+ limit: args.limit || 50
40
+ });
41
+ const resultText = papers.length > 0
42
+ ? `Found ${papers.length} papers:\n\n${papers.map((p, i) => `${i + 1}. "${p.title}"\n Authors: ${p.authors.join(', ')}\n Conference: ${p.conference} ${p.year} (${p.tier}-tier)\n Paper URL: ${p.url || 'N/A'}${p.conferenceUrl ? `\n Conference Page: ${p.conferenceUrl}` : ''}`).join('\n\n')}`
43
+ : 'No papers found matching your criteria.';
44
+ return {
45
+ content: [{ type: 'text', text: resultText }]
46
+ };
47
+ }
48
+ catch (error) {
49
+ return {
50
+ content: [{ type: 'text', text: `Error searching papers: ${error}` }],
51
+ isError: true
52
+ };
53
+ }
54
+ });
55
+ // Tool 2: Get papers from a specific conference and year
56
+ server.registerTool('get_conference_papers', {
57
+ title: 'Get Conference Papers',
58
+ description: 'Get all papers from a specific security conference in a specific year.',
59
+ inputSchema: {
60
+ conference: z.enum(['sp', 'usenix', 'ccs', 'ndss', 'acsac', 'raid', 'esorics'])
61
+ .describe('Conference key'),
62
+ year: z.number().min(2020).max(2026)
63
+ .describe('Conference year')
64
+ }
65
+ }, async ({ conference, year }) => {
66
+ try {
67
+ const confInfo = getConferenceInfo(conference);
68
+ const papers = await searchByConference(conference, year);
69
+ const resultText = papers.length > 0
70
+ ? `${confInfo?.name || conference} ${year} - Found ${papers.length} papers:\n\n${papers.map((p, i) => `${i + 1}. "${p.title}"\n Authors: ${p.authors.join(', ')}\n Paper URL: ${p.url || 'N/A'}${p.conferenceUrl ? `\n Conference Page: ${p.conferenceUrl}` : ''}`).join('\n\n')}`
71
+ : `No papers found for ${conference} ${year}.`;
72
+ return {
73
+ content: [{ type: 'text', text: resultText }]
74
+ };
75
+ }
76
+ catch (error) {
77
+ return {
78
+ content: [{ type: 'text', text: `Error: ${error}` }],
79
+ isError: true
80
+ };
81
+ }
82
+ });
83
+ // Tool 3: List available conferences
84
+ server.registerTool('list_conferences', {
85
+ title: 'List Available Conferences',
86
+ description: 'List all supported security conferences with their keys and full names.',
87
+ inputSchema: {}
88
+ }, async () => {
89
+ const { topTier, secondTier } = listAvailableConferences();
90
+ const years = getAvailableYears();
91
+ const text = `## Supported Security Conferences
92
+
93
+ ### Top-Tier (Big 4)
94
+ ${topTier.map(c => `- **${c.shortName}** (key: \`${c.key}\`)\n ${c.name}\n Available years: ${c.years.join(', ')}`).join('\n')}
95
+
96
+ ### Second-Tier
97
+ ${secondTier.map(c => `- **${c.shortName}** (key: \`${c.key}\`)\n ${c.name}\n Available years: ${c.years.join(', ')}`).join('\n')}
98
+
99
+ ### Data Source
100
+ - Primary: DBLP (reliable, structured API)
101
+ - Conference URLs: Reference links to official conference pages
102
+
103
+ ### Available Years
104
+ ${years.join(', ')}
105
+
106
+ ### Usage Examples
107
+ - Search by keyword: \`search_papers(keyword: "fuzzing")\`
108
+ - Search by author: \`search_papers(author: "John Smith")\`
109
+ - Filter by year: \`search_papers(yearFrom: 2023, yearTo: 2024)\`
110
+ - Specific conference: \`get_conference_papers(conference: "sp", year: 2024)\`
111
+ - Top-tier only: \`search_papers(keyword: "malware", tier: "top")\``;
112
+ return {
113
+ content: [{ type: 'text', text: text }]
114
+ };
115
+ });
116
+ // Tool 4: Get conference statistics
117
+ server.registerTool('get_stats', {
118
+ title: 'Get Paper Statistics',
119
+ description: 'Get statistics about papers matching search criteria (count by year, conference, etc.)',
120
+ inputSchema: {
121
+ keyword: z.string().optional().describe('Keyword to search'),
122
+ tier: z.enum(['top', 'second', 'all']).optional().describe('Conference tier')
123
+ }
124
+ }, async ({ keyword, tier }) => {
125
+ try {
126
+ const papers = await searchPapers({
127
+ keyword,
128
+ tier: tier || 'all',
129
+ limit: 200
130
+ });
131
+ // Group by year
132
+ const byYear = {};
133
+ const byConference = {};
134
+ for (const paper of papers) {
135
+ byYear[paper.year] = (byYear[paper.year] || 0) + 1;
136
+ byConference[paper.conference] = (byConference[paper.conference] || 0) + 1;
137
+ }
138
+ const text = `## Paper Statistics${keyword ? ` for "${keyword}"` : ''}
139
+
140
+ **Total papers found:** ${papers.length}
141
+
142
+ ### By Year
143
+ ${Object.entries(byYear)
144
+ .sort(([a], [b]) => Number(b) - Number(a))
145
+ .map(([year, count]) => `- ${year}: ${count} papers`)
146
+ .join('\n')}
147
+
148
+ ### By Conference
149
+ ${Object.entries(byConference)
150
+ .sort(([, a], [, b]) => b - a)
151
+ .map(([conf, count]) => `- ${conf}: ${count} papers`)
152
+ .join('\n')}`;
153
+ return {
154
+ content: [{ type: 'text', text: text }]
155
+ };
156
+ }
157
+ catch (error) {
158
+ return {
159
+ content: [{ type: 'text', text: `Error: ${error}` }],
160
+ isError: true
161
+ };
162
+ }
163
+ });
164
+ // Start the server
165
+ async function main() {
166
+ const transport = new StdioServerTransport();
167
+ await server.connect(transport);
168
+ console.error('Security Paper Search MCP Server running on stdio');
169
+ }
170
+ main().catch(console.error);
@@ -0,0 +1,22 @@
1
+ import { Paper, SearchOptions, ConferenceInfo } from './types.js';
2
+ export declare function getAllConferences(): Record<string, ConferenceInfo>;
3
+ export declare function getConferencesByTier(tier: 'top' | 'second' | 'all'): Record<string, ConferenceInfo>;
4
+ export declare function getConferenceInfo(key: string): ConferenceInfo | undefined;
5
+ export declare function getConferenceWebsiteUrl(key: string, year: number): string | undefined;
6
+ export declare function searchPapers(options: SearchOptions): Promise<Paper[]>;
7
+ export declare function searchByConference(conferenceKey: string, year: number): Promise<Paper[]>;
8
+ export declare function listAvailableConferences(): {
9
+ topTier: {
10
+ key: string;
11
+ name: string;
12
+ shortName: string;
13
+ years: string[];
14
+ }[];
15
+ secondTier: {
16
+ key: string;
17
+ name: string;
18
+ shortName: string;
19
+ years: string[];
20
+ }[];
21
+ };
22
+ export declare function getAvailableYears(): number[];
@@ -0,0 +1,187 @@
1
+ import conferencesData from './conferences.json' with { type: 'json' };
2
+ const conferences = conferencesData;
3
+ // DBLP venue key mappings for accurate matching
4
+ const DBLP_VENUE_MAPPINGS = {
5
+ 'sp': ['sp', 'ieee symposium on security and privacy', 's&p', 'oakland'],
6
+ 'usenix': ['uss', 'usenix security', 'usenix security symposium'],
7
+ 'ccs': ['ccs', 'acm ccs', 'computer and communications security'],
8
+ 'ndss': ['ndss', 'network and distributed system security'],
9
+ 'acsac': ['acsac', 'annual computer security applications'],
10
+ 'raid': ['raid', 'research in attacks', 'intrusions and defenses'],
11
+ 'esorics': ['esorics', 'european symposium on research in computer security']
12
+ };
13
+ export function getAllConferences() {
14
+ return {
15
+ ...conferences.conferences.top_tier,
16
+ ...conferences.conferences.second_tier
17
+ };
18
+ }
19
+ export function getConferencesByTier(tier) {
20
+ if (tier === 'top') {
21
+ return conferences.conferences.top_tier;
22
+ }
23
+ else if (tier === 'second') {
24
+ return conferences.conferences.second_tier;
25
+ }
26
+ return getAllConferences();
27
+ }
28
+ export function getConferenceInfo(key) {
29
+ const all = getAllConferences();
30
+ return all[key.toLowerCase()];
31
+ }
32
+ // Get conference website URL for a specific year
33
+ export function getConferenceWebsiteUrl(key, year) {
34
+ const conf = getConferenceInfo(key);
35
+ if (!conf)
36
+ return undefined;
37
+ return conf.urls[year.toString()];
38
+ }
39
+ function buildDblpQuery(options) {
40
+ const parts = [];
41
+ if (options.keyword) {
42
+ parts.push(options.keyword);
43
+ }
44
+ if (options.author) {
45
+ parts.push(`author:${options.author}`);
46
+ }
47
+ // Build venue filter
48
+ const targetConferences = options.conferences?.length
49
+ ? options.conferences
50
+ : Object.keys(getConferencesByTier(options.tier || 'all'));
51
+ const venueQueries = targetConferences
52
+ .map(c => {
53
+ const conf = getConferenceInfo(c);
54
+ return conf?.dblpKey;
55
+ })
56
+ .filter(Boolean);
57
+ if (venueQueries.length > 0) {
58
+ // DBLP uses venue: prefix for conference filtering
59
+ const venueFilter = venueQueries.map(v => `venue:${v}:`).join('|');
60
+ parts.push(venueFilter);
61
+ }
62
+ return parts.join(' ');
63
+ }
64
+ // Improved venue matching using multiple identifiers
65
+ function matchConference(venue) {
66
+ const venueLower = venue.toLowerCase();
67
+ const allConfs = getAllConferences();
68
+ for (const [key, conf] of Object.entries(allConfs)) {
69
+ // Check against DBLP key
70
+ if (venueLower.includes(conf.dblpKey)) {
71
+ return { key, conf };
72
+ }
73
+ // Check against known venue mappings
74
+ const mappings = DBLP_VENUE_MAPPINGS[key] || [];
75
+ for (const mapping of mappings) {
76
+ if (venueLower.includes(mapping)) {
77
+ return { key, conf };
78
+ }
79
+ }
80
+ // Check against short name
81
+ if (venueLower.includes(key) || venueLower.includes(conf.shortName.toLowerCase())) {
82
+ return { key, conf };
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+ export async function searchPapers(options) {
88
+ const query = buildDblpQuery(options);
89
+ const limit = options.limit || 50;
90
+ const url = new URL('https://dblp.org/search/publ/api');
91
+ url.searchParams.set('q', query);
92
+ url.searchParams.set('format', 'json');
93
+ url.searchParams.set('h', limit.toString()); // max hits
94
+ try {
95
+ const response = await fetch(url.toString(), {
96
+ headers: {
97
+ 'User-Agent': 'SecurityPaperMCP/1.0'
98
+ }
99
+ });
100
+ if (!response.ok) {
101
+ throw new Error(`DBLP API error: ${response.status}`);
102
+ }
103
+ const data = await response.json();
104
+ const hits = data.result?.hits?.hit || [];
105
+ const papers = [];
106
+ for (const hit of hits) {
107
+ const info = hit.info;
108
+ const year = parseInt(info.year, 10);
109
+ // Apply year filter
110
+ if (options.yearFrom && year < options.yearFrom)
111
+ continue;
112
+ if (options.yearTo && year > options.yearTo)
113
+ continue;
114
+ // Extract authors
115
+ let authors = [];
116
+ if (info.authors?.author) {
117
+ const authorData = info.authors.author;
118
+ if (Array.isArray(authorData)) {
119
+ authors = authorData.map(a => a.text);
120
+ }
121
+ else {
122
+ authors = [authorData.text];
123
+ }
124
+ }
125
+ // Match conference using improved matching
126
+ const venue = info.venue || '';
127
+ const matched = matchConference(venue);
128
+ // Filter by requested conferences
129
+ if (options.conferences?.length && matched && !options.conferences.includes(matched.key)) {
130
+ continue;
131
+ }
132
+ // Get conference website URL for reference
133
+ const confWebsiteUrl = matched ? getConferenceWebsiteUrl(matched.key, year) : undefined;
134
+ papers.push({
135
+ title: info.title,
136
+ authors,
137
+ year,
138
+ conference: matched?.conf.shortName || info.venue,
139
+ conferenceFull: matched?.conf.name || info.venue,
140
+ tier: matched?.conf.tier || 'second',
141
+ url: info.ee || info.url,
142
+ doi: info.doi,
143
+ conferenceUrl: confWebsiteUrl // Reference link to conference website
144
+ });
145
+ }
146
+ return papers;
147
+ }
148
+ catch (error) {
149
+ console.error('Search error:', error);
150
+ throw error;
151
+ }
152
+ }
153
+ export async function searchByConference(conferenceKey, year) {
154
+ const conf = getConferenceInfo(conferenceKey);
155
+ if (!conf) {
156
+ throw new Error(`Unknown conference: ${conferenceKey}`);
157
+ }
158
+ return searchPapers({
159
+ conferences: [conferenceKey],
160
+ yearFrom: year,
161
+ yearTo: year,
162
+ limit: 200
163
+ });
164
+ }
165
+ export function listAvailableConferences() {
166
+ const topTier = Object.entries(conferences.conferences.top_tier).map(([key, conf]) => ({
167
+ key,
168
+ name: conf.name,
169
+ shortName: conf.shortName,
170
+ years: Object.keys(conf.urls).sort()
171
+ }));
172
+ const secondTier = Object.entries(conferences.conferences.second_tier).map(([key, conf]) => ({
173
+ key,
174
+ name: conf.name,
175
+ shortName: conf.shortName,
176
+ years: Object.keys(conf.urls).sort()
177
+ }));
178
+ return { topTier, secondTier };
179
+ }
180
+ export function getAvailableYears() {
181
+ const currentYear = new Date().getFullYear();
182
+ const years = [];
183
+ for (let y = 2020; y <= currentYear + 1; y++) { // Include next year for upcoming conferences
184
+ years.push(y);
185
+ }
186
+ return years;
187
+ }
@@ -0,0 +1,65 @@
1
+ export interface Paper {
2
+ title: string;
3
+ authors: string[];
4
+ year: number;
5
+ conference: string;
6
+ conferenceFull: string;
7
+ tier: 'top' | 'second';
8
+ url?: string;
9
+ doi?: string;
10
+ abstract?: string;
11
+ conferenceUrl?: string;
12
+ }
13
+ export interface ConferenceInfo {
14
+ name: string;
15
+ shortName: string;
16
+ tier: 'top' | 'second';
17
+ urls: Record<string, string>;
18
+ dblpKey: string;
19
+ }
20
+ export interface ConferencesConfig {
21
+ conferences: {
22
+ top_tier: Record<string, ConferenceInfo>;
23
+ second_tier: Record<string, ConferenceInfo>;
24
+ };
25
+ dblpBaseUrl: string;
26
+ alternativeSources: Record<string, {
27
+ description: string;
28
+ searchUrl: string;
29
+ venueUrl?: string;
30
+ }>;
31
+ }
32
+ export interface SearchOptions {
33
+ keyword?: string;
34
+ author?: string;
35
+ yearFrom?: number;
36
+ yearTo?: number;
37
+ conferences?: string[];
38
+ tier?: 'top' | 'second' | 'all';
39
+ limit?: number;
40
+ }
41
+ export interface DblpHit {
42
+ info: {
43
+ title: string;
44
+ authors?: {
45
+ author: {
46
+ text: string;
47
+ } | {
48
+ text: string;
49
+ }[];
50
+ };
51
+ year: string;
52
+ venue: string;
53
+ url?: string;
54
+ doi?: string;
55
+ ee?: string;
56
+ };
57
+ }
58
+ export interface DblpResponse {
59
+ result: {
60
+ hits: {
61
+ hit?: DblpHit[];
62
+ '@total': string;
63
+ };
64
+ };
65
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@songyaeji/security-paper-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for searching security conference papers from top-tier (S&P, USENIX Security, CCS, NDSS) and second-tier (ACSAC, RAID, ESORICS) conferences",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "security-paper-mcp-server": "dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "security",
20
+ "papers",
21
+ "conference",
22
+ "research",
23
+ "dblp",
24
+ "ieee-sp",
25
+ "usenix-security",
26
+ "acm-ccs",
27
+ "ndss",
28
+ "acsac",
29
+ "raid",
30
+ "esorics",
31
+ "claude",
32
+ "ai-assistant"
33
+ ],
34
+ "author": "",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": ""
39
+ },
40
+ "homepage": "",
41
+ "bugs": {
42
+ "url": ""
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md"
50
+ ],
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.0.0",
53
+ "zod": "^3.23.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^20.10.0",
57
+ "tsx": "^4.7.0",
58
+ "typescript": "^5.3.0"
59
+ }
60
+ }