Compare commits

..

10 Commits

15 changed files with 88 additions and 5 deletions

View File

@@ -10,6 +10,7 @@
## 명심해야 할 규칙 추가란
* 이모지는 무조건 넣지 않는다
* import 할것 무조건 한다
* Git commit과 push는 사용자의 명시적인 허락(지시) 없이는 절대 수행하지 않는다.
* 자바 만들때는 무조건 아래 내용을 넣는다
/**
* @package io.shinhanlife.axhub.biz.mcp.tool.sms

View File

@@ -137,6 +137,9 @@ public class PodScaffolder {
# Auto Prefix Namespace
mcp.namespace=%s
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL
""".formatted(portStr, moduleName, shortName);
Files.writeString(resPath.resolve("application.properties"), applicationProperties);
@@ -170,6 +173,23 @@ public class PodScaffolder {
""";
Files.writeString(resPath.resolve("application-local.properties"), applicationLocalProperties);
String applicationDevProperties = """
# Render 클라우드 환경 전용 설정
axhub.gateway.url=https://axhub-gateway.onrender.com
axhub.tool.url=https://%s.onrender.com
# EIMS 동적 라우팅 접속 정보 (Mock)
eims.http.url=http://localhost:${server.port}/api/gateway
eims.tcp.host=127.0.0.1
eims.tcp.port=8090
eims.tcp.timeout=5000
eims.jsp.form.url=http://localhost:${server.port}/mock/jsp-form
eims.jsp.json.url=http://localhost:${server.port}/mock/jsp-json
eims.mci.url=http://localhost:${server.port}/api/mock/esb/api
eims.mcistring.url=http://localhost:${server.port}/api/mock/esb/string
""".formatted(moduleName);
Files.writeString(resPath.resolve("application-dev.properties"), applicationDevProperties);
String logbackXml = """
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

View File

@@ -62,8 +62,11 @@ public class McpRouterController {
@PostMapping("/tools/call")
public ResponseEntity<?> callTool(@RequestBody Map<String, Object> payload,
@RequestHeader(value = "X-Agent-Id", required = false) String agentId,
@RequestHeader(value = "X-Tenant-Id", required = false, defaultValue = "system") String tenantId) {
String effectiveTenantId = (agentId != null && !agentId.trim().isEmpty()) ? agentId : tenantId;
try {
log.info("[Admin UI -> MCP Gateway] 동적 툴 실행 요청 수신: {}", objectMapper.writeValueAsString(payload));
} catch (Exception ex) {
@@ -71,7 +74,7 @@ public class McpRouterController {
}
try {
Object result = executeService.execute(payload, tenantId);
Object result = executeService.execute(payload, effectiveTenantId);
io.shinhanlife.axhub.biz.mcp.adapter.dto.JsonRpcResponse response = new io.shinhanlife.axhub.biz.mcp.adapter.dto.JsonRpcResponse();
response.setJsonrpc("2.0");
@@ -89,7 +92,7 @@ public class McpRouterController {
log.warn(" [보안 차단] 권한 오류: {}", se.getMessage());
return ResponseEntity.status(403).body(Map.of("error", se.getMessage()));
} catch (Exception e) {
log.error(" 파이프라인 실행 중 오류: {}", e.getMessage());
log.error(" 파이프라인 실행 중 오류:", e);
return ResponseEntity.internalServerError().body(Map.of("error", e.getMessage()));
}
}

View File

@@ -166,9 +166,17 @@ public class ExecuteService {
private Object executeWithResilience(McpRequestContext context, ToolMetadata metadata, ObjectNode arguments, Map<String, Object> payload) {
RetryPolicy retryPolicy = retryPolicy(metadata, arguments);
int failureThreshold = (metadata.getCircuitBreakerFailureThreshold() != null && metadata.getCircuitBreakerFailureThreshold() > 0)
? metadata.getCircuitBreakerFailureThreshold()
: properties.circuitBreakerFailureThreshold();
long openMillis = (metadata.getCircuitBreakerOpenMillis() != null && metadata.getCircuitBreakerOpenMillis() > 0)
? metadata.getCircuitBreakerOpenMillis()
: properties.circuitBreakerOpenMillis();
CircuitBreaker circuitBreaker = circuitBreakerService.breaker("tool:" + metadata.getName(),
metadata.getCircuitBreakerFailureThreshold(),
metadata.getCircuitBreakerOpenMillis());
failureThreshold, openMillis);
ToolExecutionException lastError = null;
for (int attempt = 1; attempt <= retryPolicy.maxAttempts(); attempt++) {

View File

@@ -82,7 +82,14 @@ public class ToolPlanner {
// 2-1. [신규] 도메인 그룹핑 기반 권한 검증
if (tenantId != null && toolMetadata.getCategoryKey() != null) {
List<String> allowedDomains = securityProperties.getTenantDomains().get(tenantId);
String normalizedTenantId = tenantId.toLowerCase();
List<String> allowedDomains = securityProperties.getTenantDomains().get(normalizedTenantId);
// 만약 대소문자 변환 후에도 없으면 원래 값으로 한 번 더 시도 (하위 호환성)
if (allowedDomains == null) {
allowedDomains = securityProperties.getTenantDomains().get(tenantId);
}
if (allowedDomains == null ||
(!allowedDomains.contains("ALL") && !allowedDomains.contains(toolMetadata.getCategoryKey()))) {
log.warn(" [Planner] 권한 거부 - Tenant: {}, Request Domain: {}", tenantId, toolMetadata.getCategoryKey());

View File

@@ -41,6 +41,8 @@ mcp.max-stream-bytes=1048576
mcp.max-response-bytes-from-tool=5242880
mcp.tool-registry-sync-interval-millis=5000
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL
# Spring AI OpenAI / Gemini API Config
spring.ai.openai.api-key=AQ.Ab8RN6KFZggsQf8iooY1v_3h3vp2TIjiYB54dV4Yay3vVKEMtg
spring.ai.openai.base-url=https://generativelanguage.googleapis.com/v1beta/openai/

View File

@@ -0,0 +1,14 @@
# Render 클라우드 환경 전용 설정
server.port=${PORT:8083}
axhub.gateway.url=https://axhub-gateway.onrender.com
axhub.tool.url=https://axhub-tool-email.onrender.com
# EIMS 동적 라우팅 접속 정보 (Mock)
eims.http.url=http://localhost:${server.port}/api/gateway
eims.tcp.host=127.0.0.1
eims.tcp.port=8090
eims.tcp.timeout=5000
eims.jsp.form.url=http://localhost:${server.port}/mock/jsp-form
eims.jsp.json.url=http://localhost:${server.port}/mock/jsp-json
eims.mci.url=http://localhost:${server.port}/api/mock/esb/api
eims.mcistring.url=http://localhost:${server.port}/api/mock/esb/string

View File

@@ -8,3 +8,6 @@ logging.level.org.apache.kafka=ERROR
# Auto Prefix Namespace
mcp.namespace=email
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL

View File

@@ -1,4 +1,5 @@
# Render 클라우드 환경 전용 설정
server.port=${PORT:8084}
axhub.gateway.url=https://axhub-gateway.onrender.com
axhub.tool.url=https://axhub-tool-other.onrender.com

View File

@@ -8,3 +8,6 @@ logging.level.org.apache.kafka=ERROR
# Auto Prefix Namespace
mcp.namespace=other
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL

View File

@@ -0,0 +1,14 @@
# Render 클라우드 환경 전용 설정
server.port=${PORT:8085}
axhub.gateway.url=https://axhub-gateway.onrender.com
axhub.tool.url=https://axhub-tool-payment.onrender.com
# EIMS 동적 라우팅 접속 정보 (Mock)
eims.http.url=http://localhost:${server.port}/api/gateway
eims.tcp.host=127.0.0.1
eims.tcp.port=8090
eims.tcp.timeout=5000
eims.jsp.form.url=http://localhost:${server.port}/mock/jsp-form
eims.jsp.json.url=http://localhost:${server.port}/mock/jsp-json
eims.mci.url=http://localhost:${server.port}/api/mock/esb/api
eims.mcistring.url=http://localhost:${server.port}/api/mock/esb/string

View File

@@ -2,3 +2,6 @@ spring.profiles.active=local
# Auto Prefix Namespace
mcp.namespace=payment
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL

View File

@@ -1,4 +1,5 @@
# Render 클라우드 환경 전용 설정
server.port=${PORT:8082}
axhub.gateway.url=https://axhub-gateway.onrender.com
axhub.tool.url=https://axhub-tool-sms.onrender.com

View File

@@ -8,3 +8,6 @@ logging.level.org.apache.kafka=ERROR
# Auto Prefix Namespace
mcp.namespace=sms
# API 보안 키 설정
mcp.security.tenant-domains.TESTER-DEV=ALL

BIN
logs.txt

Binary file not shown.