feat(notion): 添加Notion数据库集成功能和相关脚本
添加Notion数据库集成配置和访问脚本,包括: - 配置Notion MCP服务器设置 - 添加数据库查询、内容查看和添加功能 - 创建测试脚本和集成文档
This commit is contained in:
47
NOTION_INTEGRATION.md
Normal file
47
NOTION_INTEGRATION.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Notion 数据库集成
|
||||
|
||||
此项目已配置为通过 Model Context Protocol (MCP) 与 Notion 数据库进行集成。
|
||||
|
||||
## 配置详情
|
||||
|
||||
已在 `mcp_settings.json` 中添加了 Notion 服务器配置:
|
||||
|
||||
```json
|
||||
"notion": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@notionhq/notion-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer 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\", \"Notion-Version\": \"2022-06-28\"}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 运行 Notion 数据库访问脚本
|
||||
|
||||
```bash
|
||||
python notion_database_access.py
|
||||
```
|
||||
|
||||
这将显示所有可访问的 Notion 数据库及其详细信息。
|
||||
|
||||
### 2. 手动测试 API
|
||||
|
||||
您也可以使用以下命令测试 API 连接:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer 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" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Notion-Version: 2022-06-28" \
|
||||
https://api.notion.com/v1/users/me
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 确保您的 Notion 集成已正确连接到所需的页面
|
||||
- 请妥善保管您的 API 密钥
|
||||
- 如果遇到权限错误,请检查 Notion 集成的权限设置
|
||||
11
README.md
11
README.md
@@ -1,3 +1,12 @@
|
||||
# 项目说明
|
||||
|
||||
这是一个概念验证项目,旨在通过控制我不方便控制的阿里巴巴的 DSW WebIDE,让它当牛马,它上面已经运行了 runner。
|
||||
"notion": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@notionhq/notion-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer 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\", \"Notion-Version\": \"2022-06-28\"}"
|
||||
}
|
||||
}
|
||||
85
add_notion_content.py
Normal file
85
add_notion_content.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
Script to add sample content to your Notion database
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
class NotionDatabaseUpdater:
|
||||
def __init__(self, integration_token="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"):
|
||||
self.integration_token = integration_token
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {integration_token}",
|
||||
"Content-Type": "application/json",
|
||||
"Notion-Version": "2022-06-28"
|
||||
}
|
||||
self.base_url = "https://api.notion.com/v1"
|
||||
|
||||
def create_page_in_database(self, database_id, page_title, additional_properties=None):
|
||||
"""Create a new page in the specified database"""
|
||||
url = f"{self.base_url}/pages"
|
||||
|
||||
# Basic structure for a page with a title
|
||||
data = {
|
||||
"parent": {"database_id": database_id},
|
||||
"properties": {
|
||||
"名称": { # Assuming "名称" is the title property based on our earlier discovery
|
||||
"title": [
|
||||
{
|
||||
"text": {
|
||||
"content": page_title
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Add any additional properties if provided
|
||||
if additional_properties:
|
||||
for prop_name, prop_value in additional_properties.items():
|
||||
data["properties"][prop_name] = prop_value
|
||||
|
||||
response = requests.post(url, headers=self.headers, json=data)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Error creating page: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
# Initialize the updater
|
||||
updater = NotionDatabaseUpdater()
|
||||
|
||||
# Use the database ID we found earlier
|
||||
database_id = "2fbdaaa6-ba07-804a-b48a-ce9c0a107416"
|
||||
|
||||
# Create a sample page
|
||||
sample_pages = [
|
||||
{
|
||||
"title": "今天的工作计划",
|
||||
"properties": {}
|
||||
},
|
||||
{
|
||||
"title": "学习新技能",
|
||||
"properties": {}
|
||||
},
|
||||
{
|
||||
"title": "项目进展",
|
||||
"properties": {}
|
||||
}
|
||||
]
|
||||
|
||||
print("正在向您的 Notion 数据库添加示例内容...")
|
||||
|
||||
for page in sample_pages:
|
||||
print(f"添加页面: {page['title']}")
|
||||
result = updater.create_page_in_database(database_id, page['title'], page['properties'])
|
||||
if result:
|
||||
print(f" ✓ 页面创建成功! 页面ID: {result['id']}")
|
||||
else:
|
||||
print(f" ✗ 页面创建失败")
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
103
mcp_settings.json
Normal file
103
mcp_settings.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"context7": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@upstash/context7-mcp"
|
||||
],
|
||||
"env": {
|
||||
"DEFAULT_MINIMUM_TOKENS": ""
|
||||
}
|
||||
},
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./"
|
||||
],
|
||||
"alwaysAllow": [
|
||||
"create_directory",
|
||||
"write_file",
|
||||
"edit_file"
|
||||
]
|
||||
},
|
||||
"sequentialthinking": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-sequential-thinking"
|
||||
]
|
||||
},
|
||||
"memory": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-memory"
|
||||
]
|
||||
},
|
||||
"tavily": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"tavily-mcp@0.2.3"
|
||||
],
|
||||
"env": {
|
||||
"TAVILY_API_KEY": "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"
|
||||
}
|
||||
},
|
||||
"supabase": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@supabase/mcp-server-supabase@0.5.5",
|
||||
"--access-token",
|
||||
"sbp_v0_cb9da057017b752cd9dbd232d92e482a123f787b"
|
||||
]
|
||||
},
|
||||
"n8n-mcp": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"n8n-mcp@2.12.2"
|
||||
],
|
||||
"env": {
|
||||
"MCP_MODE": "stdio",
|
||||
"LOG_LEVEL": "error",
|
||||
"DISABLE_CONSOLE_OUTPUT": "true",
|
||||
"N8N_API_KEY": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ODY1YmU5Mi0wNGVkLTRiODItYjY4OC1hODc3ODZmYTZhYzQiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzY5ODMyNjY1fQ.hy-MEy2qZzipI42mHrWtWoWx3t2Cm5UXJnHUwt7zObM",
|
||||
"N8N_HOST": "houzhongxu-n8n-free.hf.space",
|
||||
"N8N_PROTOCOL": "https",
|
||||
"N8N_PORT": "443"
|
||||
},
|
||||
"alwaysAllow": [
|
||||
"get_database_statistics",
|
||||
"list_nodes",
|
||||
"search_templates"
|
||||
]
|
||||
},
|
||||
"gitea": {
|
||||
"command": "/home/ben/comfy/modelscope/gitea-mcp",
|
||||
"args": [
|
||||
"-t",
|
||||
"stdio",
|
||||
"--host",
|
||||
" `https://gitea.tailnet-68f9.ts.net` "
|
||||
],
|
||||
"env": {
|
||||
"GITEA_ACCESS_TOKEN": "8d7d70f324796be650b79415303c31f567bf459b"
|
||||
}
|
||||
},
|
||||
"notion": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@notionhq/notion-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer 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\", \"Notion-Version\": \"2022-06-28\"}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
notion_database_access.py
Normal file
95
notion_database_access.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
Notion Database Access Script
|
||||
This script demonstrates how to connect to and access your Notion database
|
||||
using the Notion API with the configuration you have set up.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
class NotionDatabaseAccess:
|
||||
def __init__(self, integration_token="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"):
|
||||
self.integration_token = integration_token
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {integration_token}",
|
||||
"Content-Type": "application/json",
|
||||
"Notion-Version": "2022-06-28"
|
||||
}
|
||||
self.base_url = "https://api.notion.com/v1"
|
||||
|
||||
def list_databases(self):
|
||||
"""List all databases accessible with the integration token"""
|
||||
url = f"{self.base_url}/search"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "object",
|
||||
"value": "database"
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=self.headers, json=payload)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Error: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
def query_database(self, database_id):
|
||||
"""Query a specific database by ID"""
|
||||
url = f"{self.base_url}/databases/{database_id}/query"
|
||||
response = requests.post(url, headers=self.headers)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Error querying database: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
def get_database_info(self, database_id):
|
||||
"""Get information about a specific database"""
|
||||
url = f"{self.base_url}/databases/{database_id}"
|
||||
response = requests.get(url, headers=self.headers)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Error getting database info: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
# Initialize the Notion database access
|
||||
notion = NotionDatabaseAccess()
|
||||
|
||||
print("Connecting to your Notion account...")
|
||||
print("Searching for accessible databases...")
|
||||
|
||||
# List all databases
|
||||
databases_result = notion.list_databases()
|
||||
|
||||
if databases_result and 'results' in databases_result:
|
||||
databases = databases_result['results']
|
||||
|
||||
if databases:
|
||||
print(f"\nFound {len(databases)} database(s):\n")
|
||||
|
||||
for db in databases:
|
||||
db_id = db['id']
|
||||
db_title = ''.join([title.get('plain_text', '') for title in db.get('title', [])])
|
||||
|
||||
print(f"Database ID: {db_id}")
|
||||
print(f"Title: {db_title}")
|
||||
print("-" * 50)
|
||||
|
||||
# Get detailed info about each database
|
||||
db_info = notion.get_database_info(db_id)
|
||||
if db_info:
|
||||
print(f"Description: {''.join([desc.get('plain_text', '') for desc in db_info.get('description', [])])}")
|
||||
print(f"Properties:")
|
||||
for prop_name, prop_info in db_info.get('properties', {}).items():
|
||||
print(f" - {prop_name}: {prop_info.get('type', 'unknown')}")
|
||||
print()
|
||||
else:
|
||||
print("No databases found. Make sure your integration is properly connected to your Notion pages.")
|
||||
else:
|
||||
print("Failed to retrieve databases. Check your integration token and permissions.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
44
scripts/test-api-endpoints.sh
Executable file
44
scripts/test-api-endpoints.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 配置信息
|
||||
GITEA_URL="https://gitea.tailnet-68f9.ts.net"
|
||||
TOKEN="8d7d70f324796be650b79415303c31f567bf459b"
|
||||
|
||||
# 函数:测试API端点
|
||||
function test_endpoint() {
|
||||
local endpoint=$1
|
||||
echo "测试端点: $endpoint"
|
||||
|
||||
response=$(curl -s -w "\n%{http_code}" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
"$GITEA_URL$endpoint")
|
||||
|
||||
# 分离响应内容和HTTP状态码
|
||||
http_status=$(echo "$response" | tail -n1)
|
||||
response_body=$(echo "$response" | sed '$d')
|
||||
|
||||
echo "HTTP状态码: $http_status"
|
||||
if [ "$http_status" -eq 200 ]; then
|
||||
echo "✓ 成功 - 响应: $response_body"
|
||||
elif [ "$http_status" -eq 404 ]; then
|
||||
echo "✗ 未找到"
|
||||
elif [ "$http_status" -eq 403 ] || [ "$http_status" -eq 401 ]; then
|
||||
echo "✗ 访问被拒绝 (可能权限不足)"
|
||||
else
|
||||
echo "✗ 其他错误 - 响应: $response_body"
|
||||
fi
|
||||
echo "---"
|
||||
}
|
||||
|
||||
echo "=== 测试Gitea Actions Runner API端点 ==="
|
||||
echo ""
|
||||
|
||||
# 测试可能的API端点
|
||||
test_endpoint "/api/v1/actions/runners"
|
||||
test_endpoint "/api/v1/actions/runners/5"
|
||||
test_endpoint "/api/v1/admin/runners"
|
||||
test_endpoint "/api/v1/admin/runners/5"
|
||||
test_endpoint "/api/v1/user/actions/runners"
|
||||
test_endpoint "/api/v1/user/actions/runners/5"
|
||||
test_endpoint "/api/v1/users/ben/actions/runners"
|
||||
test_endpoint "/api/v1/repos/ben/modelscope/actions/runners"
|
||||
59
view_database_content.py
Normal file
59
view_database_content.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Script to view content in your Notion database
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
class NotionDatabaseViewer:
|
||||
def __init__(self, integration_token="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"):
|
||||
self.integration_token = integration_token
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {integration_token}",
|
||||
"Content-Type": "application/json",
|
||||
"Notion-Version": "2022-06-28"
|
||||
}
|
||||
self.base_url = "https://api.notion.com/v1"
|
||||
|
||||
def query_database(self, database_id):
|
||||
"""Query a specific database to get its content"""
|
||||
url = f"{self.base_url}/databases/{database_id}/query"
|
||||
response = requests.post(url, headers=self.headers, json={})
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Error querying database: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
# Initialize the viewer
|
||||
viewer = NotionDatabaseViewer()
|
||||
|
||||
# Use the database ID we found earlier
|
||||
database_id = "2fbdaaa6-ba07-804a-b48a-ce9c0a107416"
|
||||
|
||||
print("正在查询数据库内容...")
|
||||
result = viewer.query_database(database_id)
|
||||
|
||||
if result and 'results' in result:
|
||||
pages = result['results']
|
||||
print(f"在数据库中找到 {len(pages)} 个页面:\n")
|
||||
|
||||
for page in pages:
|
||||
page_id = page['id']
|
||||
# Extract the title from the page properties
|
||||
title_property = page['properties'].get('名称', {})
|
||||
if title_property and 'title' in title_property:
|
||||
title_parts = title_property['title']
|
||||
page_title = ''.join([part.get('text', {}).get('content', '') for part in title_parts])
|
||||
else:
|
||||
page_title = "[无标题]"
|
||||
|
||||
print(f"页面ID: {page_id}")
|
||||
print(f"标题: {page_title}")
|
||||
print("-" * 50)
|
||||
else:
|
||||
print("未能检索到数据库内容")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user